2013-04-13 4 views
2

Я разработчик веб-сайтов 13 лет, но я сейчас действительно учится JavaScript, так что несите меня здесь, есть много способов сделать что-то, поэтому я не уверен, когда я Правильно или неправильно.Невозможно получить доступ к этому в событии click в JavaScript

Ниже у меня есть простой скрипт Modal Dialog, над которым я работаю. Он использует Bootstrap Modal для его CSS-стороны.

Моя цель состояла в том, чтобы создать простой Modal Dialog, который отобразит и потребует действия от пользователя (нажмите ОК или отмените нажатие кнопки). Я хотел сделать его гибким для использования в будущих проектах, разрешив некоторые функции обратного вызова, которые будут переданы и вызваны, когда происходят эти события щелчка. Также некоторые другие варианты, как показать кнопку отмены или нет. (Я еще не добавил эту часть)

Так что я делаю, чтобы функция принимала объект опций/настроек. У меня также есть параметры/параметры по умолчанию, которые затем объединяются в пользовательские параметры, позволяя опциям пользователя опционально и превышать значения по умолчанию, если они присутствуют.

Я знаю, что есть несколько способов сделать это, но это метод, который я видел в нескольких проектах, которые я изучил у JS Developers, которых я уважаю.

Итак, ниже приведен код JavaScript, страница JSFiddle с кодом и страница вывода JSFiddle, чтобы увидеть результат.

В коде на полпути вниз Eсть комментарий // PROBLEM AREA DOES NOT CALL THE CALLBACK FUNCTION

В этой области у меня есть 3 вещей я различные пытался до сих пор ...

this.options.cancelCallback(); // This is what I wanted to work! 
zPanel.dialog.confirm.options.cancelCallback(); Tried this 2nd 
options.cancelCallback(); // This Works if there is a user defined callback but errors when not 

Так что моя проблема в этой области прямо сейчас когда я звоню this.options.cancelCallback(), который ДОЛЖЕН удерживать функцию обратного вызова, если пользователь прошел один из них, должен был быть переназначен этому свойству, если пользователь этого не сделал, он должен хотя бы увидеть пустой вариант по умолчанию.

Я думаю, что this часть перепутались, так как он находится внутри OnClick function..which, кстати не выглядит как обычное событие щелчка для меня, я видел его в другом проекте, и он «работал»

Итак, сообщение об ошибке, которое я получаю, это Uncaught TypeError: Cannot call method 'okCallback' of undefined

Может кто-то хорошо с JS, показать мне, как обойти эту проблему или улучшить ее даже, я пытаюсь изучить лучшие способы делать такие вещи. Спасибо

JSFiddle http://jsfiddle.net/jasondavis/dymn5/

Полный экран предварительного просмотра http://jsfiddle.net/jasondavis/dymn5/show/result/

var zPanel = { 

    dialog: { 

     confirm: function (options) { 

      var i; 

      // Default options 
      this.options = { 
       message: "",     // String: Default Message 
       cancelButton: true,    // Boolean: Show Cancel Button 
       okButton: true,     // Boolean: Show Ok Button 
       cancelCallback: function() {}, // Function: Callback function when Cancel button clicked 
       okCallback: function() {}  // Function: Callback function when Ok button clicked 
      }; 
      // Merge User defined options 
      for(i in options) { 
       if(i in this.options) { 
        this.options[i] = options[i]; 
       } else { 
        throw new Error("Notice doesn't support option: " + i); 
       } 
      } 

      var container = document.createElement('div'); 
      //template for modal window 
      container.innerHTML += '<div class="modal-content confirm">' + 
       '<div class="modal-body">' + 
       '<div>' + this.options.message + '</div>' + 
       '<div class="controls">' + 
       '<button type="button" class="btn primary">OK</button>' + 
       '<button type="button" class="btn">Cancel</button>' + 
       '</div>' + 
       '</div>' + 
       '</div>'; 

      //modal window 
      var modal = container.firstChild; 
      container = document.createElement('div'); 
      container.innerHTML = '<div class="modal-backdrop fade in"></div>'; 
      //dark background 
      var background = container.firstChild; 

      //Find OK button 
      var ok = modal.getElementsByTagName('button')[0]; 
      ok.onclick = function() { 
       modal.parentNode.removeChild(modal); 
       document.body.removeChild(background); 

       // PROBLEM AREA DOES NOT CALL THE CALLBACK FUNCTION 
       this.options.okCallback(); 
       //zPanel.dialog.confirm.options.okCallback(); 
       //options.okCallback(); // Works if there is a user defined callback 
      } 

      //Find Cancel button 
      var cancel = modal.getElementsByTagName('button')[1]; 
      cancel.onclick = function() { 
       modal.parentNode.removeChild(modal); 
       document.body.removeChild(background); 

       // PROBLEM AREA DOES NOT CALL THE CALLBACK FUNCTION 
       this.options.cancelCallback(); 
       //zPanel.dialog.confirm.options.cancelCallback(); 
       //options.cancelCallback(); // Works if there is a user defined callback 
      } 

      document.body.appendChild(background); 
      document.body.appendChild(modal); 
     } 

    } 

} 

// Create a Dialog on Click event 
$('#delete_btn').click(function() { 
    zPanel.dialog.confirm({ 
     message: 'Are you sure you want to delete action?', 
     cancelCallback: function(){alert('user pressed Cancel button')}, 
     okCallback: function() {alert('id deleted')}, 
    }); 
}); 
+0

Внутри 'confirm' метода, добавьте следующую строку:' вар само = это; '. В обработчиках клик, используйте 'self.options.cancelCallback();' ' – Ian

+1

Я веб-разработчик 13' летами что почти звучал, как вы были 13 лет :) – Ejaz

+0

@Ejay это примерно эквивалентно моим знаниям JS иногда кажется – JasonDavis

ответ

6

контексте this изменений внутри функции, особенно обработчики событий. Это также является общей проблемой при использовании setTimeout.

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

Так добавить что-то вроде этого в вашем методе confirm:

var self = this; 

И в обработчиках, используйте:

self.options.cancelCallback(); 

DEMO:http://jsfiddle.net/dymn5/3/

И так, чтобы обеспечить пройденный обратный вызов с контекстом обработчика, вы можете использовать это:

self.options.cancelCallback.apply(this, arguments); 

Такое что значение по cancelCallback «ы из this будет элемент событие происходит в, и будет иметь какие-либо аргументы, переданные к нему, как event объекта.

Это позволяет использовать это для ваших вариантов:

.confirm({ 
    cancelCallback: function (e) { 
     // `this` refers to the button 
     // `e` refers to the event 
    } 
}); 
+0

Спасибо, что я думал, что проблема была, но понятия не имела, как ее решить! Также для другой полезной информации – JasonDavis

1

В JavaScript this всегда относится к «владельцу» функции.

// example 1: function without an owner 
var displayA = function() { console.log(this.a); } 
displayA(); // undefined 

// example 2: object with a function member 
var obj = { 
    a: 1, 
    displayA: displayA 
} 

obj.displayA(); // logs "1" 
// note that obj.displayA is the exact same function as displayA. But when it is called, obj is the owner of the function. 

В первом примере у displayA нет «владельца». Если функция не имеет собственника, this автоматически предполагается глобальный объект (window в браузерах).

Во втором примере владельцем displayA является obj. В этом случае this будет относиться к obj и, таким образом, будет отображаться obj.a (то есть значение 1).

Общие методы решения этой проблемы включают в себя:

// storing `this` in a variable, when a callback function needs a reference to this 
var self = this; 
window.onload = function() { 
    // I can use self instead of this! 
    self.doStuff(); 
} 

// using Function#call or Function#apply 
// let's say I want to use the "obj" variable as the "this" reference in a function: 
function myFunction(a, b) { this.doStuff(a, b); } 
myFunction.call(obj, a, b); // after obj, pass normal function arguments 
myFunction.apply(obj, [a, b]); // after obj, pass function arguments in an array 
Смежные вопросы