2015-09-24 2 views
0

Я построил плагин, который должен преобразовать любую кнопку в форму модального стиля, с учетом URL-адреса, где можно получить форму.Плагин jQuery, использующий только значения последнего элемента

Он отлично работает только с одним элементом, но когда селектор возвращает несколько элементов, все кнопки используют данные последнего элемента, когда методы получения & вызывают внутри плагина.

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

Вот полный код. Вы увидите несколько {% django tags %} и {{ django context variables }}, но просто игнорируете их.

Спасибо!

A.

EDIT: typo; EDIT2: добавлен html; EDIT3: удалены теги django и контекстные vars.

<div class="modal fade" id="modal-1234" data-uuid="1234"> 
    <div class="modal-dialog"> 
     <div class="modal-content"> 
      <div class="modal-header"> 
       <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> 
       <h4 class="modal-title" id="title-1234">Title</h4> 
      </div> 
      <div class="modal-body" id="body-1234">Body</div> 
      <div class="modal-footer"> 
       <button type="button" class="btn btn-default" data-dismiss="modal" id="cancel-1234">Close</button> 
       <button type="button" class="btn btn-primary" id="confirm-1234">Save changes</button> 
      </div> 
     </div> 
    </div> 
</div> 

<script type="text/javascript"> 
(function($){ 
    // define the modalform class 
    function ModalForm($button){ 
     /* 
     You can use ModalForm to automate the ajax-form-modal process with TB3. 

     Usage: 

     var mf = new ModaForm($('#my-button')); // that's it 
     */ 
     self = this; 
     self.$button = $button; 
     self.$modal = $('#modal-1234'); 
     // get vars 
     self.target = self.$button.attr('data-target'); 
     self.uuid = self.$modal.attr('data-uuid'); 
     self.$modal_title = $('#title-' + self.uuid); 
     self.$modal_body = $('#body-' + self.uuid); 
     self.$modal_confirm = $('#confirm-' + self.uuid); 
     self.modal_confirm_original_text = self.$modal_confirm.html() 
     self.$modal_cancel = $('#cancel-' + self.uuid); 
     self.$alerts = $('[data-exsutils=push-alerts]').first(); 
     self.$spinner = $('<p class="center"><i class="ace-icon fa fa-spinner fa-spin orange bigger-300"></i></p>'); 
     // bind button click to _get 
     self.$button.on('click', function(e){ 
      e.preventDefault(); 
      self._get(); 
     }); 
    } 

    ModalForm.prototype._get = function(){ 
     /* 
     Issue a get request to fetch form and either render form or push alert when complete. 
     */ 
     var self = this; 
     // show modal, push spinner and change title 
     self.$modal.modal('show'); 
     self.$modal_body.html(self.$spinner); 
     self.title = typeof(
      self.$button.attr('data-title')) !== 'undefined' ? 
      self.$button.attr('data-title') : 'Modal form'; 
     self.$modal_title.html(self.title); 
     // get content 
     $.ajax({ 
      type: 'GET', 
      url: self.target, 
      statusCode: { 
       403: function(data){ 
        // close modal 
        // forbidden => close modal & push alert 
        setTimeout(function(){ 
         self.$modal.modal('hide'); 
         self.$alerts.html(data.responseText); 
        }, 500); 
       }, 
       200: function(data){ 
        // success => push form 
        // note that we will assign self.$form 
        var $response = $(data); 
        self.$form = $response.filter('form').first(); 
        self.$modal_body.html($response); 
        self.$modal_confirm.click(function(e){ 
         e.preventDefault(); 
         self._submit(self.$form); 
        }); 
       } 
      }, 
      error: function(data){ 
       console.log(data); 
      } 
     }); 
    } 

    ModalForm.prototype._submit = function(){ 
     /* 
     Post this.$form data and rerender form or push alert when complete. 
     */ 
     var self = this; 
     // change submit button to loading state 
     self.$modal_confirm.addClass('disabled').html('Loading...'); 
     // issue pot request 
     // cleanup 
     // rebind if rerender or push alerts 
     $.ajax({ 
      type: 'POST', 
      url: self.$form.attr('action'), 
      data: self.$form.serialize(), 
      statusCode: { 
       200: function(data){ 
        // this is a form error 
        // so we must rerender and rebind form 
        // else we need to rerender and rebind 
        self.$form.remove(); 
        var $response = $(data); 
        self.$form = $response.filter('form').first(); 
        self.$modal_body.html($response); 
        self.$modal_confirm.on('click', function(e){ 
         e.preventDefault(); 
         self._submit(self.$form); 
        }); 
       }, 
       201: function(data){ 
        // this means object was created 
        // so we must push an alert and clean up 
        self.$form.remove(); 
        delete self.$form; 
        self.$modal.modal('hide'); 
        self.$modal_body.html(''); 
        // we will push alerts only if there is no 201 callback 
        var callback_201 = self.$button.attr('data-callback-201'); 
        if (typeof(window[callback_201]) !== 'undefined') { 
         window[callback_201](data); 
        } else { 
         self.$alerts.prepend(data); 
        }; 
       }, 
       403: function(data){ 
        // this means request was forbidden => clean up and push alert 
        self.$form.remove(); 
        delete self.$form; 
        self.$modal.modal('hide'); 
        self.$modal_body.html(''); 
        self.$alerts.prepend(data.responseText); 
       } 
      }, 
      complete: function(){ 
       // reset button 
       self.$modal_confirm.removeClass('disabled').html(
        self.modal_confirm_original_text); 
      } 
     }); 
    } 
    window.ModalForm = ModalForm; 

    // define plugin 
    $.fn.modalForm = function(){ 
     var self = this; 
     return self.each(function(){ 
      var el = this; 
      var _ = new window.ModalForm($(el)); 
      $.data(el, 'modalform', _); 
     }); 
    } 

    // run plugin 
    $('[data-exsutils=modal-form]').modalForm(); 
})(jQuery); 
</script> 

Редактируйте @Daniel Arant:

jsFiddle с упрощенной рабочей версией коды плагина можно найти here

Примечания мной: Пожалуйста, прочитайте выбранный ответ. Этот jsfiddle + добавление var self = this даст вам полную картину проблемы и хороший способ ее устранения.

+0

Как выглядит ваш HTML-код? И из любопытства, почему вы устанавливаете window.ModalForm равным ModalForm? –

+0

Привет, добавлен HTML. О window.ModalForm, причина заключается в отладке в другом контексте, как в 'console.log (window.ModalForm)'. – misterte

+0

У меня нет абсолютно никакого опыта работы с django, так что простите меня, если это глупый вопрос, но почему вы используете теги django в коде JavaScript? В частности, я смотрю на строку, которая читает 'self.uuid = self. $ Modal = $ ('# modal - {{uuid}}');'. –

ответ

1

Источником вашей проблемы является линия self = this в конструкторе ModalForm. Поскольку вы не использовали ключевое слово var до self, интерпретатор JavaScripts считает, что self является свойством глобального объекта window и объявляет его как таковой. Поэтому каждый раз, когда вызывается конструктор ModalForm, self берет новое значение, а все ссылки на self в обработчиках событий, созданных конструктором для предыдущих кнопок, затем указывают на новый, последний экземпляр ModalForm, который был назначен к глобальному объекту self.

Чтобы устранить эту проблему, просто добавьте ключевое слово var до self = this. Это делает для себя локальную переменную, а не глобальную, а функции обратного вызова события щелчка указывают на их собственный экземпляр ModalForm вместо последнего экземпляра, который был назначен для self.

Я создал рабочую jsFiddle на основе кода, который можно найти here

Я урезанная код плагина, чтобы устранить Аякса вызовы для простоты. Я также удалил все ссылки на uuid. Когда вы получите ссылку на модальный объект jQuery, вы можете использовать метод jQuery .find() для получения ссылок на различные компоненты модального.

Если у вас есть вопросы о моей быстрой и грязной версии вашего плагина

+0

Да! Я заметил и собирался написать ответ. Я играл с JSFiddle и заметил это. Благодаря!! – misterte

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