Javascript разные переменные области видимости при вызове AJAX - PullRequest
0 голосов
/ 24 января 2012

У меня проблема с моей областью действия переменной в написанном мной простом слайдерном скрипте (я не хочу использовать готовое решение из-за низкой пропускной способности). Скрипт-слайдер вызывается на статически загружаемых страницах (http), а также на содержимом, загружаемом через AJAX. На статически загруженной странице (то есть без AJAX) сценарий работает идеально. Однако при вызове через AJAX вызываемые методы не могут найти элементы DOM, что останавливает необходимую анимацию, необходимую для слайдера.

Все события обрабатываются с помощью четного делегирования (с использованием функции on () jQuery), однако это не дает решения. Я вполне уверен, что это как-то связано со структурой и областью действия переменной скрипта, но я не могу определить, как изменить структуру. Поэтому я ищу решение, которое работает в обеих ситуациях (называется нормальным или через AJAX).

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

// Slider function
(function (window, undefined) {
    var console = window.console || undefined, // Prevent a JSLint complaint 
        doc = window.document,
        Slider = window.Slider = window.Slider || {},
        $doc = $(doc),
        sliderContainer = doc.getElementById('slider_container'),
        $sliderContainer = $(sliderContainer),
        $sliderContainerWidth = $sliderContainer.width(),
        slider = doc.getElementById('slider'),
        $slider = $(slider),
        $sliderChildren = $slider.children(),
        $slideCount = $sliderChildren.size(),
        $sliderWidth = $sliderContainerWidth * $slideCount;
    $sliderControl = $(doc.getElementById('slider_control')),
    $prevButton = $(doc.getElementById('prev')),
    $nextButton = $(doc.getElementById('next')),
    speed = 2000,
    interval,
    intervalSpeed = 5000,
    throttle = true,
    throttleSpeed = 2000;

    if (sliderContainer == null) return; // If slider is not found on page return           

    // Set widths according to the container and amount of children 
    Slider.setSliderWidth = function () {
        $slider.width($sliderWidth);
        $sliderChildren.width($sliderContainerWidth);
    };

    // Does the animation
    Slider.move = function (dir) {
        // Makes use of variables such as $sliderContainer, $sliderContainer width, etc.
    };

    // On ajax call
    $doc.on('ajaxComplete', document, function () {
        Slider.setSliderWidth();
    });

    // On doc ready
    $(document).ready(function () {
        Slider.setSliderWidth();
        interval = window.setInterval('Slider.move("right")', intervalSpeed);
    });

    // Handler for previous button
    $doc.on('click', '#prev', function (e) {
        e.preventDefault();
        Slider.move('left');
    });

    // Handler for next button
    $doc.on('click', '#next', function (e) {
        e.preventDefault();
        Slider.move('right');
    });

    // Handler for clearing the interval on hover and showing next and pervious button  
    $doc.on('hover', '#slider_container', function (e) {
        if (e.type === 'mouseenter') {
            window.clearInterval(interval);
            $sliderControl.children().fadeIn(400);
        }
    });

    // Handler for resuming the interval and fading out the controls
    $doc.on('hover', '#slider_control', function (e) {
        if (e.type !== 'mouseenter') {
            interval = window.setInterval('Slider.move("right")', intervalSpeed);
            $sliderControl.children().fadeOut(400);
        }
    });
})(window);

Структура примера HTML:

<div id="slider_control">
   <a id="next" href="#next"></a>
   <a id="prev" href="#prev"></a>
</div>
<div id="slider_container">
   <ul id="slider">
      <li style="background-color:#f00;">1</li>
      <li style="background-color:#282">2</li>
      <li style="background-color:#ff0">3</li>
   </ul>
</div>

Ответы [ 4 ]

1 голос
/ 24 января 2012

Я заметил, что у вас есть

Slider.setSliderWidth = function() {
    $slider.width($sliderWidth);
    $sliderChildren.width($sliderContainerWidth);
};

, который вызывается при завершении ajax.

Аякс ли вы обновляете DOM, давая новый элемент DOM, к которому вы можете добраться doc.getElementById('slider')? Тогда ваши var slider и jquery var $slider, скорее всего, указывают на вещи, которых больше не существует (даже если есть элемент dom с slider в качестве идентификатора). Чтобы исправить, всякий раз, когда вызывается ajax, который заменяет этот элемент, повторно инициализируйте slider и $slider, чтобы указывать на новый обернутый элемент jquery, используя ту же инициализацию, что и у вас.

slider = doc.getElementById('slider');
$slider = $(slider);

Edit:

Я не уверен, куда вы идете с проблемой переменной области, но взгляните на этот пример.

<code><pre>
<script> 
(function(){
   var a  = "something";
   function x (){
      a += "else";
   }
   function y() {
      a = "donut";
   }
   function print (){
      document.write(a +"\n");
   }
   print ();
   x();
   print ();
   y();
   print ();
   x();
   print ();
})();
document.write(typeof(a) + "\n");
</script>

Выводится в тег pre

something
somethingelse
donut
donutelse
undefined

Это не сильно отличается от того, что вы уже делаете. Поскольку a не является параметром метода и не объявляется с помощью var во вложенной области видимости, все ссылки на a в коде, определенном в вашем методе function(window,undefined){ ...}, будут ссылаться на этот a, учитывая, что a определяется локально var для этого метода. Имеет смысл?

0 голосов
/ 24 января 2012

Подождите, что загружается через Ajax? HTML-код слайдера? В этом случае Slider уже был «создан», и многие ваши переменные будут указывать на никуда (потому что этих элементов DOM не было, когда переменные были инициализированы). И они никогда этого не сделают.

0 голосов
/ 24 января 2012

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

$doc.on('click', '#slider_control #prev',function(e){
    e.preventDefault();
    Slider.move('left');
});
0 голосов
/ 24 января 2012

Для начала, конечно, вы можете заменить все getElementById, используя подход jQuery.т.е. заменить $(doc.getElementById('next')) на $('#next')

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...