Показать сообщение отдельно
  #1 (permalink)  
Старый 17.09.2015, 22:22
Новичок на форуме
Отправить личное сообщение для tomberty Посмотреть профиль Найти все сообщения от tomberty
 
Регистрация: 17.09.2015
Сообщений: 9

Почему после использования data атрибута в setTimeout, он перестаёт быть доступным ?
Добрый день.
Есть загвоздка, и я не могу понять до конца, из-за чего она возникает, поэтому попробую описать проблему, по возможности, сжато но подробно. я новичок, поэтому не судите строго за возможный каламбур...
Вообщем, я делаю карточную игруху(посередине игровое поле из 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.
Ответить с цитированием