Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Помогите с присваиванием стиля в цикле. (https://javascript.ru/forum/events/30080-pomogite-s-prisvaivaniem-stilya-v-cikle.html)

Irish.Tippler 23.07.2012 15:47

Помогите с присваиванием стиля в цикле.
 
Добрый день. Помогите пожалуйста со следующей проблемой.
Присваиваю значение onclick для элементов, с помощью цикла:
newElement.onclick = function () {this.style.backgroundImage = 'url(./img/'+this.num+'.png)';}

Тут вопросов никаких нет, но, если я хочу сделать таким образом:
newElement.onclick = function () {this.style.backgroundImage = 'url(./img/'+this.num+'.png)';
					setTimeout(function () {this.style.backgroundImage = 'none';}, 1500);}

Выдаёт мне "Cannot set property 'backgroundImage' of undefined".

В чём соль? Почему функция таймаута убирает указатель с текущего элемента?

Dim@ 23.07.2012 15:55

может так прокатит
newElement.onclick = function () {this.style.backgroundImage = 'url(./img/'+this.num+'.png)';setTimeout(function () {newElement.style.backgroundImage = 'none'}, 1500)}

Irish.Tippler 23.07.2012 16:00

Прокатило бы, если бы такой элемент был у меня один, а то:
function draw_boxes (array, count)	{
		for (k=0; k<count; k++) {

	    var parent = document.getElementById('container');
	    var newElement= document.createElement('div');
            newElement.className = 'box_element';
	    newElement.id = k;
	    newElement.num = array[k];
	    newElement.onmouseover = function () {this.style.backgroundColor=('blue');};
	    newElement.onmouseout = function () {this.style.backgroundColor=('red');};
            newElement.onclick = function () {this.style.backgroundImage = 'url(./img/'+this.num+'.png)';
					setTimeout(function () {newElement.style.backgroundImage = 'none';}, 1500);}
	        var text = array[k];
	        var textNode = document.createTextNode(k);
	        newElement.appendChild(textNode);
	        parent.appendChild(newElement);
		                    }}


Я сделал бы обращение по Id (элементы ведь формируются в цикле), но почему-то именно в этом случае - не работает. И функция получается висеть только на последнем элементе.

Dim@ 23.07.2012 16:31

Irish.Tippler,
вот так катит?
newElement.onclick = function () {th = this; this.style.backgroundImage = 'url(' + this.num + ')';
                    setTimeout(function () {th.style.backgroundImage = 'none';}, 1500);}

Irish.Tippler 23.07.2012 16:37

Цитата:

Сообщение от Dim@ (Сообщение 190960)
Irish.Tippler,
вот так катит?
newElement.onclick = function () {th = this; this.style.backgroundImage = 'url(' + this.num + ')';
                    setTimeout(function () {th.style.backgroundImage = 'none';}, 1500);}

Катит, не совсем так, как нужно, но ответ получен, спасибо ). Надо распаралеливать таймеры элементов, видимо. Почему интересно работает через присваивание?

Dim@ 23.07.2012 16:40

Цитата:

Сообщение от Irish.Tippler (Сообщение 190962)
интересно работает через присваивание?

вы про
th = this;
если да, то в переменную th записывается ссылка на объект this (newElement) который передается в setTimeout и в каждом onclick-е эта переменная своя

Irish.Tippler 23.07.2012 16:51

Цитата:

Сообщение от Dim@ (Сообщение 190964)
вы про
th = this;
если да, то в переменную th записывается ссылка на объект this (newElement) который передается в setTimeout и в каждом onclick-е эта переменная своя

То есть, setTimeout не видит локальные переменные функции, в которую она вложена?

Dim@ 23.07.2012 17:06

Irish.Tippler,
в принципе да, кстати th лучше не объявлять с var иначе функция таймаута её не увидит

Dim@ 23.07.2012 17:10

та переменная что находится в функции без var видна в глобалке
var a = 3;//просто глобальная переменная
(function (){
k = 3;//переменная будет видна в глобалке
})()
alert(a + ' ' + k);

а здесь с var выскочит ошибка что переменной k не существует
var a = 3;//просто глобальная переменная
(function (){
var k = 3;//переменная не будет видна в глобалке
})()
alert(a + ' ' + k);//будет ошибка

melky 23.07.2012 17:12

Цитата:

Сообщение от Irish.Tippler (Сообщение 190944)
В чём соль? Почему функция таймаута убирает указатель с текущего элемента?

соль в том, что Вы запутались\не знаете, что this во вложенных функциях равен window, или undefined, если скрипт исполняется в строгом режиме.

пример :

(function () {

    alert(this.foo); // "bar"

    (function () {

        alert(this.foo); // undefined
        alert(Object.prototype.toString.call(this)); // ибо this сменился на ГО\undefined.

    })();

}).call({
    foo: "bar"
});


собстно, тут практически (точнее, совсем другое, но эффект тот же) то же самое :
newElement.onclick = function () {

	this.style.backgroundImage = 'url(./img/' + this.num + '.png)';

        // вот в этой функции this сменится на window.
	setTimeout(function () {
                // а так как this.style вернёт undefined, появится то, что появилось :)
		this.style.backgroundImage = 'none';
	}, 1500);
}


как обойти ?

да просто сохранить контекст в локальной переменной - почему функция будет видеть локальную область видимости той функции, в которой определена - совершенно другой вопрос :)

newElement.onclick = function () {

*!*
	var _this = this;
*/!*

	this.style.backgroundImage = 'url(./img/' + this.num + '.png)';

	setTimeout(function () {
		// юзаем _this вместо this.
		_this.style.backgroundImage = 'none';
	}, 1500);
}


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