2009-07-16 96 views
0

我已經快速地編寫了一種產品顯示的東西,它從頁面獲取一半的輸入,另一半從AJAX查詢中獲取。JavaScript中的變量範圍問題

這裏是代碼...

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,但我決定放棄它。我的問題是,當用戶點擊一個'更多'按鈕,它顯示產品,它不會重置簡單的幻燈片(圖像var被重置,我認爲它可能與setInterval()也許,或者它似乎每次都會創建一個showProduct()的新實例)。

有誰知道我在做什麼錯?

+0

該代碼有點難以遵循。 「更多」按鈕在哪裏?您是否在談論調用showProduct的'.product-view'點擊事件?另外,你能描述一下哪些工作不正常嗎? showProduct是否第一次工作,但不是當有人點擊產品時工作? – SolutionYogi 2009-07-16 03:02:53

+0

@SolutionYogi - 對不起,關於代碼 - 我儘可能快地做到了。動態插入更多按鈕。是的,我正在談論調用showProduct()的點擊事件。它第一次工作,但點擊其他人的幻燈片放映。它顯示了與之前的圖片相關的新圖片,該圖片中點擊了之前的產品。 – alex 2009-07-16 03:06:05

回答

2

我不得不重新格式化您的代碼以真正理解發生了什麼。無論如何,我發現代碼的問題。

正如你猜對的那樣,問題在於範圍,但不是變量'圖像',而是變量'循環'。爲什麼?

此行

var cycle = setInterval(function() { 

總是創建一個新的本地循環變量(注意「變種」)時顯示產品被調用,第二次是不可訪問。這意味着該行

clearInterval(cycle); 

是基本上是無用的,因爲它總是傳遞空來調用clearInterval功能,並且不清晰的東西。這意味着當你繼續點擊'more'時,你正在創建越來越多的setInterval函數調用,永遠不會清除舊的。

無論如何,我重構了你的代碼一點點,我認爲這應該按預期工作。我做的更改如下:

  1. 刪除了this.index變量。在showProduct方法調用並使showProduct使用該變量之前,最好將'index'傳遞給showProduct,而不是設置this.index。另外,你爲什麼在變量前添加'this'?

  2. 聲明的cycler變量超出showProduct的範圍,本地爲productDisplay方法。這確保您可以在不同的showProduct調用期間訪問cycler。

  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(); 

      }); 

    }; 




}; 
1

如果您沒有用var(例如var images = ...;)定義變量,那麼它們將被視爲全局變量(window對象的成員)。

如果定義他們var那麼他們到整個功能(變量聲明甚至更早),他們在聲明。

我不能馬上看到的問題是什麼,但我可見會建議最小化變量的範圍 - 如果它們不需要是全局的,那麼確保它們不是全局的。