2012-04-01 4 views
0

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

framework.module.create('module_name',function(){ 

    //execute when starting the module 
    this.init = function(){ 

     //for example, bind a click handler 
     $('button').on('click',function(){ 
      alert('foo'); 
     }); 
    } 
}); 

имя модуля и конструктор хранится в массиве и во время загрузки страницы, выполненные как

//store 
function create(name,fn){ 
    modules[name] = fn; 
} 

//execute 
function start(){ 
    //for each module definition stored 
    var module = new modules[name](); 
    module.init(); 
} 

Теперь обработчики событий связаны с элементами. это работает, когда модуль html уже находится на странице. однако, если я попробую загрузить другую копию HTML-кода этого модуля, которая еще не имеет обработчиков, вызов start() связывает его с обработчиками, но теперь удваивает обработчик существующего/уже инициализированного HTML. нажатие кнопки на предварительно загруженном HTML теперь вызывает события щелчка дважды.

Я не могу сделать эту магию в определении модуля. Мне нужно сохранить формат «конструктор/обратный вызов». Кроме того, я не хочу, чтобы пользователи делали обходные пути для этого. это должно быть сделано в рамках кода.

Как выполнить скрипт модуля только для вновь добавленного, точно идентичного HTML?

или

Как предотвратить сценарий от влияния на уже инициализирована HTML?

+0

ли начать принимать параметр, и если это нуль, то делать все, должно решить вашу проблему. –

ответ

2

Два ответа на дилемму: область выбора jQuery или делегирование событий.

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

framework.module.create('module_name',function(context){ 

    if (!context) { 
     context = document; 
    } 

    //execute when starting the module 
    this.init = function(){ 

     //for example, bind a click handler 
     $('button', context).on('click',function(){ 
      alert('foo'); 
     }); 
    } 
}); 

Но, в этом примере, start должны быть изменены также, принять свой собственный context аргумент, и передать его вместе с модулем:

function start(context){ 
    //for each module definition stored 
    var module = new modules[name](context); 
    module.init(); 
} 

Вы бы затем использовать его так: start("#myDiv");. И в случае, если вы не передали контекст, он автоматически захватит document для контекста селектора. Однако я не уверен, что вы хотите сделать это, передавая что-то другое в start каждый раз, когда он вызывается.

Или ... вы можете использовать делегирование:

framework.module.create('module_name',function(){ 

    //execute when starting the module 
    this.init = function(){ 

     //for example, bind a click handler 
     $(document).on('click', 'button', function(){ 
      alert('foo'); 
     }); 
    } 
}); 

Это придает обработчик событий к document объекта, и запускает его, когда он видит, что его пузырь цепь проходит через 'button'. Но это все равно добавляет обработчик события каждый раз, когда вызывается module.init. Таким образом, вы можете добавить счетчик в конструктор модуля, только назначение обработчика событий, когда это первый объект:

framework.module.create('module_name',function(){ 
    var totalModules = 0; 
    return function(){ 

     totalModules += 1; 
     //execute when starting the module 
     this.init = function(){ 

      // if this is the first module being created, and 
      // no event handlers have yet been attached... 
      if (totalModules === 1) { 
       $(document).on('click', 'button', function(){ 
        alert('foo'); 
       }); 
      } 
     } 
    } 
}()); 
Смежные вопросы