Добрый день.
Есть загвоздка, и я не могу понять до конца, из-за чего она возникает, поэтому попробую описать проблему, по возможности, сжато но подробно. я новичок, поэтому не судите строго за возможный каламбур...
Вообщем, я делаю карточную игруху(посередине игровое поле из 9 ячеек. 3 по горизонту 3 по вертикали. От игрового поля слева находятся ваши карты, а справа карты компа. У каждой карты есть 4 цифры слева, справа, сверху и снизу. По этим цифрам происходит сравнение между картами.)
Ход игрока реализован при помощи jquery, draggable и droppable. Ход компа осуществляется в droppable свойстве drop: при помощи append. Вся логика написана и всё работает.
И собственно теперь к проблеме, сейчас хочу сделать чтобы действие append после перетаскивания происходило с 2 сек задержкой. Написал код, и append работает как задумывалось, НО потом вся логика рушиться, т.к. элемент, который я передаю append в дальнейшем везде перестаёт быть доступным (выдаёт undefined).
Код выглядит вот так:
// перемешиваю колоду. //
var arr = [0,1,2,3,4];
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
shuffle(arr);
var cards = new Array();
for (var i=0; i<5; i++) {
cards[i] = $('.ssComp:eq('+(arr[i])+')');
}
// ------------------------------------- //
$('.game-field').droppable({
activeClass: 'active-th',
hoverClass: 'hover-th',
drop: function(event, ui) {
$card = $(ui.draggable);
$(this).prepend($card);
var self = $(this);
var appendCard = function(arg) {
var y = $(arg).append(cards.shift()).find('img').css({
'border': '10px solid #FF0000',
'width': '150px',
'height': '150px'
}).animate({
'width': '100%',
'height': '100%'
});
var q = $(arg).droppable('disable');
return y, q;
}
setTimeout(function(){appendCard.call(self, '[data-id='+(self.data('id')+1)+']')}, 2000);
У всех ячеек игрового поля есть data-id. По дата атрибуту собственно и происходит везде обращение. Функция appendCard вставляет карту компа справа от той ячейки, в которую user перетащил свою карту. (логику проверок на вставку в поле я тут опустил, т.к. это не важно сейчас).
В дальнейшем по игровой логике, вставленную компом карту, нужно будет сравнивать с соседними картами по всем сторонам (справа, снизу, слева, сверху). Обращение к этим ячейкам выглядит вот так:
var insertComp = $('[data-id='+($(this).data('id')+1)+'] .ssComp');
var topSs = $('[data-id='+($(this).data('id')-2)+'] .ss')
var topComp = $('[data-id='+($(this).data('id')-2)+'] .ssComp');
var bottomComp = $('[data-id='+($(this).data('id')+4)+'] .ssComp');
var bottomSs = $('[data-id='+($(this).data('id')+4)+'] .ss');
var rightSs = $('[data-id='+($(this).data('id')+2)+'] .ss');
var rightComp = $('[data-id='+($(this).data('id')+2)+'] .ssComp');
var leftSs = $('[data-id='+($(this).data('id')+0)+'] .ss');
var leftComp = $('[data-id='+($(this).data('id')+0)+'] .ssComp');
ss - класс колоды юзера, ssComp - колоды компа. (разметку страницы если нужно могу выложить)
у них так же есть data-user=1 для .ss и data-user=2 для .ssComp
Дальше сравниваю карту:
setTimeout(function(){leftInsert()}, 500); // с той, что СЛЕВА от неё //
setTimeout(function(){topInsert()}, 500); // с той, что СВЕРХУ над ней //
setTimeout(function(){rightInsert()}, 500); // с той, что СПРАВА от неё //
setTimeout(function(){bottomInsert()}, 500); // с той, что СНИЗУ под ней //
приведу пример одной из функций, т.к. они все подобны.
// функция сравнение ответной карты с той, что снизу под ней //
function bottomInsert () {
var x;
if (insertComp.data('user') != bottomComp.data('user') || insertComp.data('user') != bottomSs.data('user')) {
if (insertComp.data('bottom') > bottomComp.data('top') || insertComp.data('bottom') > bottomSs.data('top')) {
bottomComp.data('user', 2);
bottomSs.data('user', 2);undefined
if (bottomSs.data('user') === 1) {
x = green(bottomSs);
u2++;
} else if (bottomSs.data('user') === 2) {
x = red(bottomSs);
u2 +=2;
u1--;
}
if (bottomComp.data('user') === 1) {
x = green(bottomComp);
u2++;
} else if (bottomComp.data('user') === 2) {
x = red(bottomComp);
u2 +=2;
u1--;
}
}
}
return x, u1, u2;
}
Извиняюсь, что кучу всего приплёл, но теперь ПЕРЕХОДИМ К САМОМУ ИНТЕРЕСНОМУ.
В принципе сама проблема представлена ниже, а всё что выше, для понимания из-за чего это может возникать.
И так, если я пишу вот так:
appendCard('[data-id='+($(this).data('id')+1)+']');
То всё прекрасно работает. Крата вставляется справа от перетаскиваемой, производятся все логические проверки на сравнения с другими картами и т.д. Правда, конечно, за исключением того, что карта вставляется сразу же без задержки.
Если тут вызвать:
alert($('[data-id='+($(this).data('id')+1)+'] .ssComp').data('user')); // возвращает 2. как и положено
Ну а мне как раз нужно сделать паузу в этом моменте.
Поэтому я пишу так:
setTimeout(function(){appendCard.call(self, '[data-id='+(self.data('id')+1)+']')}, 1000);
Здесь карта вставляется куда нужно, но логика проверок отваливается.
Если вызвать:
alert($('[data-id='+($(this).data('id')+1)+'] .ssComp').data('user')); // возвращает undefined.
хотя если наполнить игровые поля картами и например тут вызвать так:
alert($('[data-id='+($(this).data('id')+4)+'] .ssComp').data('user')); // вернёт 2 как и положено (или 1 в зависимости от карты и какой класс указать ss или ssComp).
Главное что this работает корректно.
alert($('[data-id='+($(this).data('id')+1)+']').data('id')); // так же возвращает верное значение. ( в зависимости куда перту перетащить)
хотя с таймером:
setTimeout(function(){alert($('[data-id='+($(this).data('id')+1)+']').data('id'))}, 1500); // возвращает undefined.
Чего-то я явно не понимаю. Но что-то явно загадочное происходит в следовании друг за другом этих методов setTimeout.