1
  • tem.jqw.Callback object contains an executable function, a CSS selector. and a looping delay.
  • tem.jqw.wait waits for jQuery to be loaded and then goes through an array of tem.jqw.Callback objects and executes their functions after having found an element with the CSS selector passed in.

The problem I am having is in the run function within the tem.jqw.Callback object. When the run function is called the first time, if the element exists, everything is fine and the executable function runs OK. However, if the element does not yet exist, and we need to loop, the function loses scope after setTimeout(this.run, 100) executes once. For example, when the run function is executing the second time, this.selector or this.fn become undefined. How can I work around this without using global variables? Thanks in advance.

if (typeof tem !== "object") {
  tem = {};
}

tem.jqw = {};
tem.jqw.retries = 0;
tem.jqw.maxRetries = 100;
tem.jqw.delay = 100;
tem.jqw.callbacks = [];

tem.jqw.Callback = function (fn, selector, delay) {
  this.fn = fn;
  this.selector = (typeof selector === "string" && selector.length > 0) ? selector : document;
  this.delay = (typeof delay === "number" && delay > 0 && delay < 1000) ? delay : 100;

  this.retries = 0;
  this.maxRetries = 100;

  this.start = function () {
    this.run();
  };

  this.run = function () {
    if (jQuery(this.selector).length > 0) {
      console.log("[OPDEBUG] tem.jqw.Callback.run says: " + this.selector.toString() + " is ready. Executing callback function...");
      this.fn();
    } else {
      this.retries++;
      console.log("[OPDEBUG] tem.jqw.Callback.run says: typeof this.selector " + typeof this.selector);
      console.log("[OPDEBUG] tem.jqw.Callback.run says: Waiting for " + this.selector.toString() + "...");
      if (this.retries < this.maxRetries) {
        setTimeout(this.run, 100);
      }
    }
  };
};

tem.jqw.wait = function () {
  if (typeof jQuery === "function") {
    console.log("[OPDEBUG] tem.jqw.wait says: jQuery is ready.");
    for (var i = 0; i < tem.jqw.callbacks.length; i++) {
      if (typeof tem.jqw.callbacks[i] === "object" && typeof tem.jqw.callbacks[i].start === "function") {
        console.log("[OPDEBUG] tem.jqw.wait says: Executing callback function " + (i + 1) + "...");
        tem.jqw.callbacks[i].start();
      }
    }
  } else {
    tem.jqw.retries++;
    console.log("[OPDEBUG] tem.jqw.wait says: " + "Waiting for jQuery " + tem.jqw.retries + "...");
    if (tem.jqw.retries < tem.jqw.maxRetries) {
      setTimeout(tem.jqw.wait, tem.jqw.delay);
    }
  }
};

tem.jqw.callbacks.push(new tem.jqw.Callback(function () {
  jQuery('.hero-inner:first a').css('background-image', 'url("https://www.thedogs.co.nz/Files/PhotoFinishImages/11298_89160.jpg")')
}, ".hero-inner:first"));
tem.jqw.callbacks.push(new tem.jqw.Callback(function () {
  jQuery('.RR-placeholder ul li:first').hide();
}, ".RR-placeholder ul li:first"));
tem.jqw.wait();

1
  • 2
    setTimeout(this.run.bind( this ), 100) Commented Aug 14, 2015 at 11:28

1 Answer 1

1

you can use bind to set this

change this.run() to

this.run.bind(this)

Its better to assign this to another variable eg)

var self = this;

and then pass around self for better readability

Sign up to request clarification or add additional context in comments.

2 Comments

this.run.bind(this) works! Where do I do: var self = this? Would that be the first thing to do in the run function? And then, would I need to do: setTimeout(self.run, 100)? Thanks!
I prefer a name describing the object rather than self, which is no more descriptive than this or that. Maybe callback = this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.