Область применения переменных в Javascript - PullRequest
2 голосов
/ 05 октября 2010

У меня проблемы с пониманием объема "этого" в этом сценарии. Я могу вызвать каждую из этих функций, например: this.startTracking (); изнутри объекта переключения трекера времени. Однако, когда я пытаюсь выполнить код: Drupal.timeTracker.prototype.stopTracking (); Он теряет всю область видимости переменных, и мой запрос GET становится неопределенным. Как я могу отключить stopTracking () при загрузке?

    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));
    }
  });
};

Ответы [ 3 ]

1 голос
/ 05 октября 2010

Я просто возьму небольшой фрагмент:

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

Ваша проблема в том, что когда вы создаете функцию связывания, this внутри нее будет ссылаться на $(window), поэтому вам нужносоздать копию этого, чтобы иметь возможность ссылаться на него внутри этой новой функции.

0 голосов
/ 05 октября 2010

Когда вы вызываете new Drupal.timeTracker(this), он создает новый объект. Этот объект наследуется от Drupal.timeTracker.prototype. Внутри методов этого объекта this устанавливается для самого объекта. Drupal.timeTracker.prototype не объект, а просто шаблон, из которого могут быть сформированы новые экземпляры объекта; Как резак печенья, это не очень хорошо поесть. Самое главное, что ни одно из внутреннего состояния вашего реального таймера не живет там.

Когда вы вызываете Drupal.timeTracker.prototype.stopTracking, он вызывается по шаблону, а не по реальному объекту. Если вы позвоните tracker.stopTracking(), все будет в порядке. Вы не можете вызвать this.stopTracking(), потому что когда вы хотите вызвать stopTracking, вы находитесь в обработчике событий для onbeforeunload, поэтому ваш this будет объектом window.

0 голосов
/ 05 октября 2010

Ответ googletorp должен работать, но только краткое замечание:

Я полагаю, что проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь позвонить:

Drupal.timeTracker.prototype.stopTracking();

Вместо этого, я думаю,это должно быть:

Drupal.timeTracker.stopTracking();

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

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