2010-10-05 4 views
2

Je n'arrive pas à comprendre la portée de 'this' dans ce scénario. Je suis capable d'appeler chacune de ces fonctions comme: this.startTracking(); de l'intérieur de l'objet de commutation de suivi de temps. Cependant, lorsque j'essaie d'exécuter le code: Drupal.timeTracker.prototype.stopTracking(); Il perd toute la portée des variables et ma requête GET devient indéfinie. Comment puis-je déclencher stopTracking() onbeforeunload?Portée des variables en Javascript

Drupal.behaviors.dynamicTimeTracker = function (context) { 
    $('form.node-time-tracker', context).each(function() { 
    new Drupal.timeTracker(this); 
    }); 
}; 

/** 
* A time tracker switch object 
*/ 
Drupal.timeTracker = function (form) { 
    var tracker = this; 
    this.form = form; 
    this.nid = $('#'+ form.id +' input[name="nid"]').attr('value'); 
    this.uid = $('#'+ form.id +' input[name="uid"]').attr('value'); 
    this.button = $('#'+ form.id +' input[type="submit"]'); 
    this.url = Drupal.settings.time_tracker.url + '/' + this.nid + '/' + this.uid; 
    this.counter = $('#'+ form.id +' .counter'); 

    this.initialize(); // TODO: make sure this function is called regularly to make sure trackers are in synch 
    this.startTracking(); 
    $(window).bind('beforeunload', function() { 
    Drupal.timeTracker.prototype.stopTracking(); // need help here 
    }); 
}; 

/** 
* Initialize the time tracker 
*/ 
Drupal.timeTracker.prototype.initialize = function() { 
    var tracker = this; 

    $.ajax({ 
    type: "GET", 
    url: tracker.url, 
    dataType: 'json', 
    success: function (status) { 
     $(tracker.counter).countdown({compact:true, since:-status['time']}).countdown('resume'); 

     if (status['status'] == 'ongoing') { 
     $(tracker.button).toggle(
      function() { 
      tracker.stopTracking(); 
      return false; 
      }, 
      function() { 
      tracker.startTracking(); 
      return false; 
      } 
     ); 
     $(tracker.counter).countdown('resume'); 
     $(tracker.button).val(Drupal.t('Stop')); 
     $(tracker.form).removeClass('node-time-tracker-start').addClass('node-time-tracker-stop'); 
     } 
     else { 
     $(tracker.button).toggle(
      function() { 
      tracker.startTracking(); 
      return false; 
      }, 
      function() { 
      tracker.stopTracking(); 
      return false; 
      } 
     ); 
     $(tracker.counter).countdown('pause'); 
     $(tracker.button).val(Drupal.t('Start')); 
     $(tracker.form).removeClass('node-time-tracker-stop').addClass('node-time-tracker-start'); 
     } 
    }, 
    error: function (xmlhttp) { 
     alert(Drupal.ahahError(xmlhttp, tracker.startURL)); 
    } 
    }); 
}; 

/** 
* Starts time tracking 
*/ 
Drupal.timeTracker.prototype.startTracking = function() { 
    var tracker = this; 

    // Ajax GET request for starting time tracker 
    $.ajax({ 
    type: "GET", 
    url: tracker.url + '/start', 
    dataType: 'json', 
    success: function (status) { 
     $(tracker.counter).countdown('change', {since: -status['time']}).countdown('resume'); 
     $(tracker.button).val(Drupal.t('Stop')); 
     $(tracker.form).removeClass('node-time-tracker-start').addClass('node-time-tracker-stop'); 
    }, 
    error: function (xmlhttp) { 
     alert(Drupal.ahahError(xmlhttp, tracker.startURL)); 
    } 
    }); 
}; 

/** 
* Stops time tracking 
*/ 
Drupal.timeTracker.prototype.stopTracking = function() { 
    var tracker = this; 

    // Ajax GET request for stopping time tracker 
    $.ajax({ 
    type: "GET", 
    url: tracker.url + '/stop', 
    dataType: 'json', 
    success: function (status) { 
     $(tracker.counter).countdown('change', {since: -status['time']}).countdown('pause'); 
     $(tracker.button).val(Drupal.t('Start')); 
     $(tracker.form).removeClass('node-time-tracker-stop').addClass('node-time-tracker-start'); 
    }, 
    error: function (xmlhttp) { 
     alert(Drupal.ahahError(xmlhttp, tracker.startURL)); 
    } 
    }); 
}; 

Répondre

1

Je vais juste prendre un petit extrait:

this.startTracking(); 
$(window).bind('beforeunload', function() { 
    // this is defined by the above function definition 
    tracker.stopTracking(); 
}); 

Votre problème est que lorsque vous créez la fonction de liaison, this à l'intérieur, se référera à $(window), vous devez créer une copie de ceci, pour pouvoir le référencer dans cette nouvelle fonction.

+0

Merci, c'était exactement exact ... J'apprécie votre aide! – plunder

0

La réponse de googletorp devrait fonctionner, mais juste une note rapide:

Je crois que le problème que vous rencontrez est parce que vous essayez d'appeler:

Drupal.timeTracker.prototype.stopTracking(); 

Au lieu de cela, je pense que ce devrait-il être:

Drupal.timeTracker.stopTracking(); 

Je ne crois pas que vous êtes censé appeler des fonctions sur le prototype, mais plutôt sur l'objet dont le prototype que vous avez modifié.

+0

J'ai essayé, et Firebug m'a dit que ma fonction n'était pas définie – plunder

+0

Intéressant ... Je suppose que j'ai plus à apprendre sur les prototypes JS. – netRealm

+0

Vous n'héritez pas du prototype avant d'instancier l'objet (vous devrez créer une instance de Drupal.timeTracker pour pouvoir utiliser stopTracking sans passer par l'objet prototype) – xj9

0

Lorsque vous appelez new Drupal.timeTracker(this), il crée un nouvel objet. Cet objet hérite de Drupal.timeTracker.prototype. À l'intérieur des méthodes de cet objet, this est défini sur l'objet lui-même. Drupal.timeTracker.prototype n'est pas l'objet, mais simplement un modèle à partir duquel de nouvelles instances de l'objet peuvent être formées; Comme un emporte-pièce, ce n'est pas très bon à manger. Plus important encore, aucun de l'état interne de votre minuterie réelle vit là.

Lorsque vous appelez Drupal.timeTracker.prototype.stopTracking, il est appelé sur le modèle et non sur l'objet réel. Si vous appelez tracker.stopTracking(), tout ira bien. Vous ne pouvez pas appeler this.stopTracking(), car lorsque vous souhaitez appeler stopTracking, vous êtes dans le gestionnaire d'événements pour onbeforeunload, donc votre this sera l'objet window.

Questions connexes