0

私は次のフィドルを持っています:http: //jsfiddle.net/mauricederegt/HMkcD/1/

一連の色付きのブロック(div)が含まれています。1をクリックしてブロックを表示します。生成されるHTMLは次のようになります。

<div id="plane">
<div class="tile tile1" block-id="1" style-id="1" style="left:0px; top:0px"></div>
<div class="tile tile2" block-id="2" style-id="2" style="left:100px; top:0px"></div>
<div class="tile tile1" block-id="3" style-id="1" style="left:200px; top:0px"></div>
<div class="tile tile2" block-id="4" style-id="2" style="left:0px; top:100px"></div>
<div class="tile tile1" block-id="5" style-id="1" style="left:100px; top:100px"></div>
<div class="tile tile2" block-id="6" style-id="2" style="left:200px; top:100px"></div>
<div class="tile tile1" block-id="7" style-id="1" style="left:0px; top:200px"></div>
<div class="tile tile2" block-id="8" style-id="2" style="left:100px; top:200px"></div>
<div class="tile tile1" block-id="9" style-id="1" style="left:200px; top:200px"></div>
<div class="tile tile3" block-id="10" style-id="3" style="left:50px; top:50px"></div><div class="tile tile4" block-id="11" style-id="4" style="left:150px; top:50px"></div>
<div class="tile tile4" block-id="12" style-id="4" style="left:50px; top:150px"></div>
<div class="tile tile3" block-id="13" style-id="3" style="left:150px; top:150px"></div>
</div>

ssブロックをクリックしたときに、色付きのブロック/divにクラスを追加したい。このクリックされたブロックが選択されたブロックになります。次に、クリックして別のブロックを選択します。これら2つのブロックのスタイルIDが同じである場合、それらのブロックを削除したいと思います。ssそうでない場合は、クラスを再度削除します。

これを行うために、次のコードを作成しました。

$('#plane').click(function(){                            //the click function
    var clickedBlock = $(this);                          //get the data of the clicked div/block
    clickedBlock.addClass('ss');                         //add class ss to the clicked div/block
    if (blockSelected) {                                 //if div/block is selected
       if ($(blockSelected).attr('block-id') == clickedBlock.attr('block-id')) {  //if block-id of the selected div equals the block-id of the clicked div
           clickedBlock.removeClass('ss');               //remove class ss
       } else {                                          //else
          if ($(blockSelected).attr('style-id') == clickedBlock.attr('style-id')) { //if style selected div equals style clicked div
              $(blockSelected).addClass('x');            //ad class x to selected div or better: remove div
              clickedBlock.addClass('x');                //ad class x to clicked div or better: remove div
              totalTiles = totalTiles - 2;               //deduct 2 of the total tiles
               } else {                                  //if not equal styles
              $(blockSelected).removeClass('ss');        //remove class ss form the selected div
              clickedBlock.removeClass('ss');            //remove class ss from the clicked div
           }
        }
        blockSelected = null;
   } else {
        blockSelected = this;
   }
});

問題は、それを機能させることができないということです。最初は正しくないと思いますが、うまくいかないように見える#planeので、そこにどのコードを入れるべきかわかりません。#plane div

ありがとうございました!

4

3 に答える 3

1

OP、

on()@Rodrigo Assisが提案した方法を使用することは、戦いの半分です。つまり、DOMの読み込み後に作成された要素にリスナーをアタッチしようとしていました。このため、直接イベントを使用することはできません。代わりに、委任されたイベントを使用する必要があります。古い方法はでしlive()たが、その後非推奨になりました。on()新しい標準です。詳細はこちら

あなたが説明したロジックに関しては、私はあなたのコードを少し作り直して、それを最適化しました。これは、より凝縮されたロジックで、あなたが求めることを達成すると確信しています。以下は要約です、これは更新されたフィドルです

JS

 ...
    var pairs = [];
    $('#plane').on('click', '.tile', function () { 
        $(this).addClass('ss');
        pairs.push($(this));
        if (pairs.length == 2) {
             if ($(pairs[0]).attr('style-id') === $(pairs[1]).attr('style-id') && $(pairs[0]).attr('block-id') != $(pairs[1]).attr('block-id')) {
                $(pairs[0]).remove();
                $(pairs[1]).remove();
                pairs = [];
            } else {
                $(pairs[0]).removeClass('ss');
                $(pairs[1]).removeClass('ss');
                pairs = [];
            }
        }
    });
 ...

簡単に

私たちが望んでいるのは、基本的に次のように言うことです。

  • ユーザーがblockAをクリックし、強調表示します
  • ユーザーがblockBをクリックし、強調表示します
    • ブロックのスタイルIDが同じ場合は、それらを削除します
    • それ以外の場合は、両方のハイライトを解除します

この場合、pairsアレイはあなたの友達です。

ああ、もう1つ、元のコードには次のようなものがありましたtotalTiles = totalTiles - 2totalTilesへの参照としてマッピングをお勧めし$('.tile').lengthます。私はあなたのコードを調べましたが、なぜあなたがその値を減らしているのか理解できなかったようです。

それが役に立てば幸い。

-編集-

app.jsの185行目の条件を更新して、同じブロックが2回選択された場合に、ペアとして扱われないようにしました。上記のフィドルとコードの要点が修正されました。

于 2013-03-18T20:26:33.970 に答える
1

私はあなたがやりたいことをやっていると思います。

私はあなたのフィドルを変えました。planeを使用してのHTMLを作成した直後に、次el.innerHTML = html.join('');を追加しました。

         $(el).find('.tile').click(function () {
                //get the data of the clicked div/block
                var clickedBlock = $(this); 
                //add class ss to the clicked div/block
                clickedBlock.addClass('ss'); 
                if (blockSelected) { 
                    //if div/block is selected
                    if ($(blockSelected).attr('block-id') == clickedBlock.attr('block-id')) { 
                        //if block-id of the selected div equals the block-id of the clicked div
                        //remove class ss
                        clickedBlock.removeClass('ss'); 
                    } else { //else
                        if ($(blockSelected).attr('style-id') == clickedBlock.attr('style-id')) { 
                            //if style selected div equals style clicked div
                            //ad class x to selected div or better: remove div
                            $(blockSelected).remove(); 
                            //ad class x to clicked div or better: remove div
                            clickedBlock.remove(); 
                            //deduct 2 of the total tiles
                            totalTiles = totalTiles - 2; 
                        } else { //if not equal styles
                            //remove class ss form the selected div
                            $(blockSelected).removeClass('ss'); 
                            //remove class ss from the clicked div
                            clickedBlock.removeClass('ss'); 
                        }
                    }
                    blockSelected = null;
                } else {
                    blockSelected = this;
                }
            });

これで、同じsytle-idを持つ2つのブロックをクリックすると、それらが削除されます。最初のブロックをクリックしてから一致しないブロックをクリックすると、スタイルが削除されます。

それがあなたが望んでいたことだと思います

于 2013-03-18T20:31:25.917 に答える
1

まったく異なるアプローチに興味がある場合は、次のことを検討してください。

var BLOCK_PAIR = (function() {//Singleton NAMESPACE pattern.
    //Private vars
    var blocks = $(),
        delay = 500,
        selClss = 'ss',
        compareAttr = 'style-id',
        disabled = false;

    //Private functions
    var select = function(e) {
        var $b = $(e.target);
        if(disabled) return;
        if( blocks.length == 1 && blocks.not($b).length == 0 ) {
            reset();//allow first block to be deselected
            return;
        }
        if( blocks.length >= 2 ) reset(); //should never happen
        blocks = blocks.add($b.addClass(selClss));
        compare();
    };
    var compare = function() {
        if(blocks.length == 2) {
            if(blocks.eq(0).attr(compareAttr) == blocks.eq(1).attr(compareAttr)) {
                setTimeout(remove, delay);
            }
            else {
                setTimeout(reset, delay);
            }
            disabled = true;//inhibit block selection during timeout delay.
        }
    };
    var remove = function() {
        blocks.remove();
        reset();
    };
    var reset = function() {
        blocks.removeClass(selClss);
        blocks = $();
        disabled = false;
    };

    //Expose private functions as public methods
    return {
        select: select,
    };
})();

$(function() {
    $('#plane').on('click', '.tile', BLOCK_PAIR.select);
});

デモ: http: //jsfiddle.net/5NyJw/

于 2013-03-19T01:13:36.570 に答える