2009-07-16 2 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(); 

      }); 


    }; 




}; 

Важной функцией является showProduct(). Теперь, как правило, я не пишу JS, как это, но я решил отложить это. Моя проблема заключается в том, что когда пользователь нажимает кнопку «больше» и отображает гордость, он не сбрасывает простое слайд-шоу (сбрасываются изображения var, я думаю, что это связано с setInterval(), возможно, или Кажется, это делает новый экземпляр showProduct() каждый раз).

Кто-нибудь знает, что я делаю неправильно?

+0

Код немного сложный для подражания. Где кнопка «больше»? Вы говорите о событии click. Product-view, которое вызывает showProduct? Кроме того, не могли бы вы описать, что не работает должным образом? Работает ли showProduct в первый раз, но не когда кто-то нажимает на продукт? – SolutionYogi

+0

@SolutionYogi - Извините за код - я сделал это как можно быстрее. Чем больше кнопка вставлена ​​динамически. И да, я говорю о событии click, вызывающем showProduct(). Он работает в первый раз, но клики на других заставляют слайд-шоу. Он отображает новый, перемежающийся с предыдущими изображениями в галерее, из которых предыдущие продукты я нажал. – alex

+0

Работает ли мой код так, как ожидалось? – SolutionYogi

ответ

2

Мне пришлось переформатировать ваш код, чтобы действительно понять, что происходит. Во всяком случае, я нашел проблему с кодом.

Как вы правильно догадались, проблема связана с областью действия, но не с переменными «изображениями», а с переменным «циклом». Зачем?

Эта линия

var cycle = setInterval(function() { 

всегда создает новую переменную локального цикла (обратите внимание на «вар»), который не доступен, когда showProduct вызывается во второй раз. Это означает, что эта линия

clearInterval(cycle); 

по существу бесполезен, как это всегда проходит нуль функции clearInterval и не проясняет ничего. Это означает, что по мере того, как вы продолжаете нажимать «больше», вы создаете все больше вызовов setInterval, никогда не очищаете старые.

В любом случае, я немного переработал ваш код, я думаю, что это должно работать должным образом. Изменения, которые я сделал:

  1. Удалена переменная this.index. Лучше передать «index», чтобы showProduct вместо установки this.index перед вызовом метода showProduct и заставить showProduct использовать эту переменную. Кроме того, почему вы префикс переменной с этим?

  2. Объявление о переменной cycler за пределами области showProduct, локально к способуОтображение продукта. Это гарантирует, что вы можете получить доступ к cycler во время различных вызовов 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, то они видны всем функции (даже до того, как переменная объявлена), они объявлены в.

Я не могу сразу увидеть, в чем проблема, но я рекомендовал бы свести к минимуму объем ваших переменных - если они не должны быть глобальными, убедитесь, что они не являются глобальными.

Смежные вопросы