Один ID для двух элементов.

  • Автор темы Автор темы Zest
  • Дата начала Дата начала
Статус
Закрыто для дальнейших ответов.

Zest

Забанен
Топикстартер
Сообщения
2 967
Реакции
70
Сознавая что тут не тусуются монстры веб-дизайна, тем не менее подкидываю задачку. Сразу говорю что решения нет, есть только обход условий.

Имеется div (или любой другой контейнер) в котором ничего нет. Заданы действительные размеры и контейнер отображает только свой фон - фотку. Контейнер имеет ID для того, чтобы скрипт его нашел и подвинул фон. Это не роловер по ховеру, скрипт двигает фон по 10 пикселов за 20 раз в течении 1 секунды. То есть это анимация. Фон двигается известным способом: .style.backgroundPosition=

Все работает зашибись. Но если в этот контейнер поместить текст - скрипт вылетает с ошибкой "'style' is null or not an object" Данная ошибка буквально означает что данный элемент не имеет атрибута style вообще или это вообще не элемент. Но поиск по инету показал что чаще всего это связано с косяком в коде где один ID используется для двух или более элементов.

Но тут-то ровно один элемент. Все работает. Вписываем текст - не работает.

Разобрав содержимое контейнера находим текстовую ноду - #text - которая, похоже и идентифицируется по тому же самому ID, но не имеет атрибута style и вообще не элемент.

Можно отфильтровать действие скрипта понаставив проверок типа if(.nodeType==1), но хотелось бы понять природу явления и как решить задачу системно.

То есть нужно получить референс на объект так, чтобы он не затрагивал текстовые ноды этого объекта.
 
Ответ: Один ID для двух элементов.

Наверно фигово очень разбираюсь в JS и HTML, потому что мало что понял... Особенно причем здесь nodeType...

код покажите...
 
Ответ: Один ID для двух элементов.

При том что только у елемента может быть атрибут style.

А если вы фигово разбираетесь, то зачем отвечаете?

Сырец вам не поможет. Там стандартная процедура получения референса на элемент - getElementById, и стандартное изменение атрибута style этого еле-мента.

В науке есть предположение что надо получать референс на атрибут. Это я только что предположил.
 
Ответ: Один ID для двух элементов.

PHP:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">

<head>
<meta http-equiv="Content-Type" content="text/html;charset=windows-1251" />
<title>test</title>
<link rel="stylesheet" type="text/css" href="style.css" media="screen" />
</head>

<script type="text/javascript">
window.onload = function() {

for (var i=100; i<1200; i++)
{
	moveBackground(i);
	pausecomp(50);


};
	
};

function moveBackground(i)
{
document.getElementById("test").style.backgroundPosition=i+"px "+i+"px";
}

function pausecomp(millis) 
{
var date = new Date();
var curDate = null;

do { curDate = new Date(); } 
while(curDate-date < millis);
} 

</script>

<body>

<div id="test">
<p>some text</p>
<p>some more text</p>
</div>


</body>
</html>

вот так у меня работает, но застрял с паузой... setTimeout что-то не работает :(
 
Ответ: Один ID для двух элементов.

Ясно, короче... позориться кодом не хотите просто =)
Другого и не ожидалось =)
 
Ответ: Один ID для двух элементов.

Так надо не сетТаймаут, а сетИнтервал.
 
Ответ: Один ID для двух элементов.

Анимация подвижкой фона не оказалась таким простым делом как я сначала предполагал. Но в общем за пол-дня было все отлажено и прекрасно работало пока преобразование в хтмл шло на стороне клиента (я так и не могу найти второй Экспрешн с поддержкой пхп, поэтому приходится вот так извращаться). Но когда я проверил Оперой код преобразованный в хтмл на сервере, оказалось что в Опере анимация не пашет. Потому что Опера добавляет текстовую ноду нулевой длины в дивижн который по определению должен быть пустым от такого хлама. Добавляет потому что закрывающий тег оказывается на следующей строке.

Если бы я писал в хтмл, то просто избавился бы от переноса и все было бы ок - но я писал на xsl и поэтому не мог контролировать такие нюансы - где окажется закрывающий тэг решал интерпрентатор XSLT. Пришлось задавать вопросы на форуме - нихрена не помогло. Вылупились такие же спецы как DCat и только хлопали глазами. Поэтому после небольшого исследования было все тупо обставлено проверками на тип ноды после чего анимация заработала везде.

Вот код ява-скрипта:

Код:
// ДВИГАЕТ ФОН СЛОЯ и КАРТИНКУ В СЛОЕ
var myTimer = null;
var cnt = 1;


// ОТФИЛЬТРОВАТЬ ТЕКСТОВУЮ НОДУ
// сделано из-за того что Опера добавляет пустую текстовую ноду в див при переносе закрывающего тега на следующую строку
function getElementNode(n) {
	var child = n.childNodes;
		for (var i=0; i<child.length; i++) {
			if (child[i].nodeType == 1) {
			return child[i];
			}
		}
}

// ДВИГАЕТ
function moveBG(a) {
	breakAnim();
	var e=document.getElementById(a);
	var d = getElementNode(e);
	// 	если есть дочерний элемент и адрес второй картинки то определить коэффициент инкремента
	if(d!=null) {
		// определить ширину картинки
		var img = new Image();
		img.src=d.style.backgroundImage.replace(/(url)|\)|\(|"/g,'');
		var ofd=img.width;
		// если картинка еще не загружена то ширина = 0 тогда выход.
		if (ofd==0){return false;}
		// из отношения ширины контейнера и ширины фотки определяется значение инкремента в пикселах
		var mul =  Math.round(e.clientWidth/ofd*10);
	}

	myTimer=setInterval( (function() {animate(e, d, ofd, mul);} ),10);
}

// ВОЗВРАЩАЕТ
function returnBG(a) {
	var e=document.getElementById(a);
	var d = getElementNode(e);
	breakAnim();
	if (e!=null) {if(e.nodeType==1){e.style.backgroundPosition = 'center top';}}
	if (d!=null) {if(d.nodeType==1){d.style.backgroundPosition = 'right top';}}
}

// СОБСТВЕННО АНИМАЦИЯ
function animate(e, d, ofd, mul) {
	if (e!=null) { if(e.nodeType==1){ e.style.backgroundPosition = 'center ' + (cnt*11) + 'px';}}
	if (d!=null) { if(d.nodeType==1){ d.style.backgroundPosition = ofd + (cnt*mul) + 'px top';}}

	if (++cnt>=20) {
		breakAnim();
	}
}

// ОСТАНОВИТЬ АНИМАЦИЮ
function breakAnim() {
	if (myTimer != null) {clearInterval(myTimer);}
	cnt=1;
}
 
Ответ: Один ID для двух элементов.

Анимацию в действии, если хотите, можете посмотреть тут http://www.edem24.ru/

И тогда вам станет понятно зачем в скрипте сделана поддержка второго слоя анимации.

В хтмл можете не смотреть - его писал не я, а интерпрентатор XSL шаблона. Но ни шаблона, ни источника - XML - вам не увидеть. А было бы прикольно.
 
Ответ: Один ID для двух элементов.

В коде ява скрипта остались комментарии к прежней версии. Сначала я передавал адрес второй картинки в качестве аргумента, потому что не знал как очистить возвращаемое значение от хлама. То есть я знал о функции replace, но протупил с ее использованием поскольку в упор не мог найти документацию на использованный синтаксис. У меня сначала было replace().replace(). и так далее что есть маразм. Меня этот сишный синтаксис изрядно достает, кстати. Косая влево затем char - это я понимаю, но почему косая вправо, скобки открываются, строка, скобки закрываются, символ объединения. Строка же должна быть в кавычках.

Позже случайно наткнулся в сети на пример получения адреса фоновой картинки и там красиво было все сделано. Добавил только еще замену символа дюймов, поскольку Опера за каким-то хреном кавычит URL.

Теперь наличие второй картинки определяется по наличию дочернего элемента. Поскольку функция сугубо приватная, то этим вторым элементом является либо A с фоном либо DIV с фоном.
 
Ответ: Один ID для двух элементов.

Skvoznyak и еще, никакого смысла в функции pausecomp нету. Ява скрипт выполняется асинхронно, то есть ничего подобного басиковскому DoEvents нету. Если вы запустили "сонную" функцию, то это не значит что скрипт остановится на ней пока не закончатся итерации. Нет, он запустит ее в новом треде и пойдет дальше выполняться. Дальше у вас подвижка фона - подвинется. Затем пойдет дальше, запустит еще один тред для "сонной" функции, и сразу же, не дожидаясь пока она там проспится - перейдет к следующей команде, а там подвижка фона.

Смотрите, вот еще мулька - показ анимированной картинки в процессе загрузки основной:

Код:
// ПОКАЗ ИНДИКАТОРА ЗАГРУЗКИ КАРТИНКИ
function picBack(divID, divBackground) { 
	var d=document.getElementById(divID);
	var img = new Image();
	d.style.backgroundImage = 'url(img/wait.gif)';
	img.onload = function() {  d.style.backgroundImage = 'url(' + img.src + ')'; };
	img.src = divBackground;
}

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

Но смотрите, сначала идет строка с кодом для события onload, а за ней идет строка начинающая загрузку. В синхронной логике нужно начать загрузку, а затем проверять когда загружено. Но ява - сука асинхронная - поэтому сначала мы создаем новый тред ожидающий событие onload, а затем начинаем загрузку.

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

Но, не ява-скрипта, а процессора. Ява скрипт давным давно выполнился и выгружен из памяти, но открытые им треды еще живут и выполняются.
 
Ответ: Один ID для двух элементов.

Это, кстати, делает возможным прерывание анимации. Поскольку скрипт ее запустивший уже давно сгинул оставив процессор разхлебывать треды, то мы можем запустить новый скрипт и покилять эти треды чтобы остановить анимацию. Если бы скрипт выполнялся синхронно, то нам нельзя было бы остановить анимацию пока он полностью бы не выполнился. Или вешать на него прерывания, что есть геморрой.
 
Ответ: Один ID для двух элементов.

Предваряя возможное обсуждение этого сайта. Задача состояла в том, чтобы из минимума информации которая запросто бы уместилась ровно на 1 странице, раздуть ее на несколько страниц, то есть подделаться под полноценный, навороченный сайт. Там даже есть страница он-лайн заказа, которая фактически нахрен не нужна на этом этапе. Но фактически весь сайт содержится в той самой одной странице, но не хтмл, а XML.

Кстати, да, увидеть XML и XSL можно, но надо знать название файлов и мне надо убрать ссылку на шаблон из индекса, поскольку он конвертит в XML, а не в HTML. Убрал. Теперь если сразу после урла набрать /index.xml - увидите единственную информационную страницу сайта. А если набрать /index.xsl - шаблон оформления заглавной страницы. Шаблонов там несколько, причем каждый из них отвечает за свою часть - заголовок, меню, подвал, содержание. Все легко комбинируется путем include и вызова данного шаблона в нужном месте.

Это вам не 3v06учие фреймы!
 
Ответ: Один ID для двух элементов.

Однако если у вас Опера или какой-нить другой бровзер который не умеет показывать XML иерархично - то вы увидите просто текстовый дамп всех узлов.
 
Ответ: Один ID для двух элементов.

Щас позырим, осилит монстр стандартов верстки DCat эту всю информацию, или сдуецо. :)
 
Ответ: Один ID для двух элементов.

>Skvoznyak и еще, никакого смысла в функции pausecomp нету

Zest, я полностью согласен. смысл в ней по-моему такой, что она просто тормозит броузер в целом... но, как я написал выше, с setTimeout/setInterval я что-то не разобрался, поэтому сделал вот так - грязно (поначалу вообще alert() воткнул, но надоело нажимать OK). Меня же интересовало не создание рабочей анимации, а именно вопрос того, будет ли двигаться фон при наличии текста в <div></div>, или броузер выдаст ошибку. ошибки я не увидел, но у Вас, оказывается, условия позаковыристей )
 
Ответ: Один ID для двух элементов.

А, вот в чем дело. Я оказывается не прокрутил ваш код до конца. Ну так я же говорю о текстовой ноде, об #text.

А вы текст вставили в параграфе - <p>. Следовательно он сразу и стал элементом. В этом случае у него нет id, потому что вы его не определили, а родительский id не наследуется.

В том и проблема что голый текст в диве как бы наследует этот ID и получается вместо одного элемента по ID - какие-то полтора.

Перенос строки в хтмле по идее не должен добавлять ничего в рендер страницы, но видите, некоторые оперы не согласны с этим и добавляют.
 
Ответ: Один ID для двух элементов.

Имеется следующая классификация типов узлов

Код:
/* if (!window.Node) var Node =
    {
      ELEMENT_NODE                :  1,
      ATTRIBUTE_NODE              :  2,
      TEXT_NODE                   :  3,
      CDATA_SECTION_NODE          :  4,
      ENTITY_REFERENCE_NODE       :  5,
      ENTITY_NODE                 :  6,
      PROCESSING_INSTRUCTION_NODE :  7,
      COMMENT_NODE                :  8,
      DOCUMENT_NODE               :  9,
      DOCUMENT_TYPE_NODE          : 10,
      DOCUMENT_FRAGMENT_NODE      : 11,
      NOTATION_NODE               : 12
    } */

Если вас такая конструкция

<div id="myDiv"><p>text</p></div>

То первый ребенок (firstChild) будет типа 1 и имени P и собственного ID у него не будет.

А если такая:

<div id="myDiv">text</div>

То будет типа 3 и имени #text, и что составляет предмет проблемы - у него появляется родительский ID.
 
Ответ: Один ID для двух элементов.

у меня в опере (на маке) ничего не меняется, даже если голый текст вставить, без <p>. только что проверил - ошибок не выдает, бэкграунд двигает
 
Ответ: Один ID для двух элементов.

Чудесное сочетание "в опере на маке".

Кстати, был такой ответ на мой вопрос. Чувак начал спрашивать в каком бровзере я проверял. Я ему ответил, типа, мне что теперь, найти подходящий бровзер который вытерпит глюки моего кода и рекомендовать всем посетителям его использовать? Nice solution!

Может быть и вы также хотите посоветовать?

Я использую Оперу для проверки в качестве бровзера стоящего на самых маргинальных позициях. То есть я думаю что охватываю диапазон интерпрентаций проверяя код в Ишаке и Опере.

Но Опера для Мака - это ничто. В смысле этого практически не существует с учетом подмножества юзеров мака юзающих оперу (хотя, с учетом менталитета макюзера выбор оперы был бы крайне органичным). Кстати, Опера очень толерантна к косякам в коде и стилях, что смазывает симптомы и крайне затрудняет поиск бага.

http://www.w3schools.com/browsers/browsers_stats.asp
 
Ответ: Один ID для двух элементов.

Строго говоря #text у меня появляется не в тэге div, а в тэге <a>. Тэг оформляется стилем display: block с указанием размеров. Просто на головной странице две картинки поэтому одна div, а вторая для ховера - a.

Кстати, сначала было вообще красиво - вторая картинка была img и двигалась как img. Но оказалось что когда ее граница пересекает пиксел указателя мыши, то генерируется событие mouseover и анимация перезапускается.

По этому поводу я тоже на веб-форуме задавал вопрос (англоязычном) - ответа нет.
 
Статус
Закрыто для дальнейших ответов.