2009-07-16 14 views
0

私はすぐに、ページからの入力の半分とAJAXクエリからの半分の入力を取得するような種類の商品表示をコーディングしました。ここでJavaScriptの可変範囲の問題

)は、重要な機能がshowProduct(ある

function productDisplay() { 


    products = []; 

    this.index = 0; 

    setupProductDisplay(); 

    processListItems(); 

    showProduct(); 

    function setupProductDisplay() { 

     var productInfoBoxHtml = '<div id="product-info"><h3 class="hide-me"></h3><span id="dimensions" class="hide-me"></span><div id="product-gallery"><img alt="" src="" /></div><ul id="product-options" class="hide-me"><li id="spex-sheet"><a href="" rel="external">Download full spex sheet</a></li><li id="enlarge-image"><a href="" rel="lightbox-gallery">Enlarge image</a></li></ul><div id="product-description" class="hide-me"></div><span id="top"></span><span id="bottom"></span><span id="side"></span><span class="loading"></span></div>'; 
     $('#products').after(productInfoBoxHtml); 
    } 

    function processListItems() { 

     $('#products > li') 
      .append('<span class="product-view">View</span>') 
      .filter(':even') 
      .addClass('even') 
     .end() 
      .each(function() { 

       products.push({ 
        id: $(this).find('h3').html(),  
        title: $(this).find('h3').html(), 
        dimensions: $(this).find('.dimensions').html(), 
        description: $(this).find('.product-description').html() 
       }); 

     }) 
     .find('.product-view') 
      .click(function() { 

       var $thisListItem = $(this).parents('ul li'); 

       var index = $('#products > li').index($thisListItem); 

       this.index = index; 

       showProduct(); 


      }); 

    }; 


    function showProduct() { 

      var index = this.index; 

      console.log('INDEX = ' + index); 

     // hide current data 
      $('#product-info') 
      .show() 
      .find('.hide-me, #product-gallery') 
       .hide() 
      .parent() 
       .find('.loading') 
       .show(); 



      // get data contained in the page 

      $('#product-info') 
      .find('h3') 
       .html(products[index].title) 
      .parent() 
      .find('#dimensions') 
       .html(products[index].dimensions) 
      .parent() 
      .find('#product-description') 
       .html(products[index].description) 


      // get id & then product extra info 

      var id = $('#products > li').eq(index).attr('id').replace(/id-/, ''); 




      var downloadPath = PATH_BASE + 'downloads/'; 

      var imagePath = PATH_BASE + 'images/products/' 

      $.getJSON(PATH_BASE + 'products/get/' + id + '/', 
       function(data){   
        var file = '';  
        var images = []; 

        file = data.file; 

        images = data.images; 

        // show file list item if there is a file 
        if (file) { 
        $('#spex-sheet').show().find('a').attr({ href: downloadPath + file }); 
        } else {     
        $('#spex-sheet').hide(); 
        } 

        // image gallery 



        if (images.length != 0) { 
        $('#product-gallery').show(); 
        // preload image thumbnails 
        $.each(images, function(i, image){ 
         var img = new Image(); 
         img.src = imagePath + 'thumb-' + image; 
         img = null; 
        }); 

        // set first image thumbail and enlarge link 
        if (images[0]) { 
         $('#enlarge-image').show().find('a').attr({ href: imagePath + images[0] }); 
         $('#product-gallery img').attr ({ src: imagePath + 'thumb-' + images[0]}) 

        } 

        console.log(images); 

        // setup gallery 

        var currentImage = 0; 

        clearInterval(cycle); 

        console.log(cycle); 



        var cycle = setInterval(function() { 
         console.log(currentImage + ' = ' + index); 
         if (currentImage == images.length - 1) {    
          currentImage = 0;    
         } else {     
          currentImage ++;     
         }; 

         var obj = $('#product-gallery'); 

         var imageSource = imagePath + 'thumb-' + images[currentImage];   
         obj.css('backgroundImage','url(' + imageSource +')');  
         obj.find('img').show().fadeOut(500, function() { $(this).attr({src: imageSource}) }); 
         $('#enlarge-image a').attr({ href: imagePath + images[currentImage] });   
        }, 5000); 


        // setup lightbox 
        $("#enlarge-image a").slimbox({/* Put custom options here */}, null, function(el) { 
         return (this == el) || ((this.rel.length > 8) && (this.rel == el.rel)); 
        }); 



        } else { 
        // no images 

        $('#enlarge-image').hide(); 
        $('#product-gallery').hide(); 

        }; 


        // show the product info 
        $('#product-info') 
        .find('.hide-me') 
         .remove('#product-gallery, #spex-sheet') 
          .show() 
       .parent() 
        .find('.loading') 
         .hide(); 

      }); 


    }; 




}; 

...コードです。今では一般的に私はこのようなJSを書いていませんが、私はそれを行こうと決めました。私の問題は、ユーザーが 'more'ボタンをクリックしてプロウエクトを表示したときに、単純なスライドショーをリセットしないことです(画像varはリセットされています、おそらくsetInterval毎回showProduct()の新しいインスタンスを作成しているようです。

誰かが間違っていることを知っていますか?

+0

コードは少し難しいです。 「more」ボタンはどこですか?あなたはshowProductを呼び出す '.product-view'クリックイベントについて話していますか?また、正常に動作していないことを説明できますか? showProductは初めて動作しますが、誰かが製品をクリックしたときに動作しませんか? – SolutionYogi

+0

@SolutionYogi - コードは申し訳ありません。できるだけ早く行いました。より多くのボタンが動的に挿入されます。はい、私はshowProduct()を呼び出すclickイベントについて話しています。これは初めてのことですが、他のサイトへのクリックはスライドショーを狂わせます。これはギャラリーに以前の画像が散在している新しいものを表示しています。 – alex

+0

私のコードは期待通りに機能しましたか? – SolutionYogi

答えて

2

実際に何が起こっているのかを理解するためにコードを再フォーマットする必要がありました。とにかく、コードに問題が見つかりました。

正しく推測したように、問題はスコープにありますが、変数 'images'ではなく変数 'c​​ycle'で示されます。どうして?

このライン

var cycle = setInterval(function() { 

は常にshowProductが二度目呼び出されたときにアクセスすることはできません新しいローカルサイクル変数(「VAR」を気づか)を作成します。つまり、この行は常にclearInterval関数にnullを渡して何もクリアしないため、この行がこの行であることを意味します。つまり、「more」をクリックし続けると、setInterval関数呼び出しがますます作成され、古いものは決してクリアされません。

とにかく、あなたのコードを少しリファクタリングしました。これは期待どおりに動作するはずです。私がした変更は:

  1. 削除されました。 showProductメソッド呼び出しの前にthis.indexを設定し、showProductにその変数を使用させる代わりに、showProductに 'index'を渡す方が良いでしょう。また、なぜ変数に 'this'を付けるのですか?

  2. 宣言されたcycler変数は、showProductのスコープ外で、productDisplayメソッドに対してローカルです。これにより、さまざまなshowProduct呼び出し中にサイクラーにアクセスできることが保証されます。

  3. コードの理解と維持を容易にするために、showFile、showGallery、showProductInfoという名前の小さな関数を作成しました。

ご質問がある場合や、コードがまだ機能しない場合はお知らせください。

function productDisplay() { 

    //Instead of keeping this.index variable, it's better to make showProduct function 
    //take index variable. 

    products = []; 
    setupProductDisplay(); 
    processListItems(); 

    //We have to define cycler outside the showProduct function so that it's maintained 
    //in between showProduct calls. 
    var cycler = null; 

    showProduct(0); 

    function setupProductDisplay() 
    { 
     var productInfoBoxHtml = '<div id="product-info"><h3 class="hide-me"></h3><span id="dimensions" class="hide-me"></span><div id="product-gallery"><img alt="" src="" /></div><ul id="product-options" class="hide-me"><li id="spex-sheet"><a href="" rel="external">Download full spex sheet</a></li><li id="enlarge-image"><a href="" rel="lightbox-gallery">Enlarge image</a></li></ul><div id="product-description" class="hide-me"></div><span id="top"></span><span id="bottom"></span><span id="side"></span><span class="loading"></span></div>'; 
     $('#products').after(productInfoBoxHtml); 
    } 

    function processListItems() 
    { 
     $('#products > li') 
      .append('<span class="product-view">View</span>') 
      .filter(':even') 
      .addClass('even') 
      .end() 
      .each(
       function() 
       { 
        products.push({ 
            id: $(this).find('h3').html(),   
            title: $(this).find('h3').html(), 
            dimensions: $(this).find('.dimensions').html(), 
            description: $(this).find('.product-description').html() 
          }); 

       }) 
      .find('.product-view') 
      .click(function() 
        { 
         var $thisListItem = $(this).parents('ul li'); 
         showProduct($('#products > li').index($thisListItem)); 

        } 
       ); 

    }; 

    function showFile(file) 
    { 
     if (file) 
     { 
      $('#spex-sheet').show().find('a').attr({ href: downloadPath + file });  
     } 
     else 
     {          
      $('#spex-sheet').hide(); 
     } 
    } 

    function showGallery(images) 
    { 
     if(! images || !images.length || images.length == 0) 
     { 
      $('#enlarge-image').hide(); 
      $('#product-gallery').hide(); 
      return; 
     } 

     $('#product-gallery').show(); 

     $.each(images, 
       function(i, image) 
       { 
        var img = new Image(); 
        img.src = imagePath + 'thumb-' + image; 
        img = null; 
       }); 

     // set first image thumbail and enlarge link 
     if (images[0]) 
     { 
      $('#enlarge-image').show().find('a').attr({ href: imagePath + images[0] }); 
      $('#product-gallery img').attr ({ src: imagePath + 'thumb-' + images[0]}) 
     } 

     var currentImage = 0; 
     clearInterval(cycler); 

     cycler = setInterval(
       function() 
       { 
        currentImage = currentImage == images.length - 1 ? 0 : currentImage++; 
        var obj = $('#product-gallery'); 

        var imageSource = imagePath + 'thumb-' + images[currentImage];     
        obj.css('backgroundImage','url(' + imageSource +')');   
        obj.find('img').show().fadeOut(500, function() { $(this).attr({src: imageSource}) }); 
        $('#enlarge-image a').attr({ href: imagePath + images[currentImage] });     
       }, 5000); 



     $("#enlarge-image a").slimbox({/* Put custom options here */}, null, function(el) { 
             return (this == el) || ((this.rel.length > 8) && (this.rel == el.rel)); 
           }); 

    }; 

    function showProductInfo() 
    { 
     $('#product-info') 
      .find('.hide-me') 
       .remove('#product-gallery, #spex-sheet') 
       .show() 
      .parent() 
       .find('.loading') 
       .hide(); 
    } 

    function showProduct(index) 
    { 
     $('#product-info') 
      .show() 
      .find('.hide-me, #product-gallery') 
       .hide() 
      .parent() 
       .find('.loading') 
       .show(); 

     // get data contained in the page 
     $('#product-info') 
      .find('h3') 
       .html(products[index].title) 
      .parent() 
       .find('#dimensions') 
        .html(products[index].dimensions) 
       .parent() 
       .find('#product-description') 
        .html(products[index].description) 

     // get id & then product extra info 
     var id = $('#products > li').eq(index).attr('id').replace(/id-/, ''); 

     var downloadPath = PATH_BASE + 'downloads/'; 
     var imagePath = PATH_BASE + 'images/products/' 

     $.getJSON(PATH_BASE + 'products/get/' + id + '/', 
      function(data) 
      {   
       showFile(data.file); 
       showGallery(data.image); 
       showProductInfo(); 

      }); 

    }; 




}; 
+0

うわー!あなたに貸しがある。今すぐチェックしてお知らせします。 – alex

+0

私は別の半時間ほどそうするつもりです。 – SolutionYogi

+0

少し修正する必要がありました。しかし、これは本当にありがとう。もしできれば、私は10回投票するだろう。 – alex

1

変数をvar(たとえばvar images = ...;)で定義しないと、グローバル変数(windowオブジェクトのメンバー)とみなされます。

あなたがvarでそれらを定義した場合、彼らは彼らがで宣言されている(変数が宣言される前でも)全体機能に表示されます。

私はすぐに問題が何であるかを見ますが、私はできません変数の範囲を最小限にすることをお勧めします。変数がグローバルである必要がない場合は、変数がグローバルでないことを確認してください。