1
\$\begingroup\$

My current task is to extend some JavaScript of a framework we are using. A pop-up should slide in, instead of just appear in the middle of the window. So I have overridden one of the framework's methods, and do at the end this:

AdfDhtmlPage.prototype.showMessages = function (componentId) {

// Some code here

function slideIn() {
  var maxTop = windowHeight - (thisHeight + 18);
  var tempTop = parseInt(popupElement._rootElement.style.top);

  if (maxTop >= tempTop) {
    setTimeout(function () {
      AdfPage.PAGE.clearMessages(componentId);
    },5000);
    return;
  }

  popupElement._rootElement.style.top = tempTop - 1 + 'px';
  setTimeout(slideIn, 20);
}
slideIn();
}

Everything worked just fine, but then I thought that the slideIn method should somehow be a behavior of the popupElement. During refactoring I encountered a behavior that was new to me and which is here called binding loss. So what I came up with is this:

AdfDhtmlPage.prototype.showMessages = function (componentId) {
    // Some code here
    popupElement._slideIn(popupElement, componentId);
}

AdfDhtmlSimpleFloat.prototype._slideIn = function(element, componentId) {
    var maxTop = AdfAgent.AGENT.getWindowHeight() - (element.getHeight() + 18);
    var thisTop = parseInt(element._rootElement.style.top);

    if (maxTop >= thisTop) {
        setTimeout(function () {
            AdfPage.PAGE.clearMessages(componentId);
        },5000);
        return;
    }

    element._rootElement.style.top = thisTop - 1 + 'px';
    setTimeout(function() {
        element._slideIn(element, componentId);
    }, 20);
}

So when calling the _slideIn method of popupElement I need to pass popupElement as argument. So I can access the objects properties, after the method has been called via setTimeout (When the binding loss happens).

However, this seems odd to me. So I would like to ask you to review my design. Maybe someone comes up with a better solution?


that was, what I wanted to do:

AdfDhtmlPage.prototype.showMessages = function (componentId) {
    // Some code here
    popupElement._slideIn(componentId);
}

AdfDhtmlSimpleFloat.prototype._slideIn = function(componentId) {
    var maxTop = AdfAgent.AGENT.getWindowHeight() - (this.getHeight() + 18);
    var thisTop = parseInt(this._rootElement.style.top);

    if (maxTop >= thisTop) {
        setTimeout(function () {
            AdfPage.PAGE.clearMessages(componentId);
        },5000);
        return;
    }

    this._rootElement.style.top = thisTop - 1 + 'px';
    setTimeout(this._slideIn, 20);
}
\$\endgroup\$
5
  • \$\begingroup\$ Why would you assume that your element should be bound inside the AdfDhtmlSimpleFloat object? (is popupElement an AdfDhtmlSimpleFloat?). I notice from the ADF docs that they warn you not to use these classes at all, are you sure you want to? \$\endgroup\$
    – JohnMark13
    Commented Sep 4, 2013 at 11:14
  • \$\begingroup\$ Yes the popupElement is an AdfDhtmlSimpleFloat object. We are aware of the possible draw-backs of using their classes, but didn't see any other way. \$\endgroup\$ Commented Sep 4, 2013 at 11:26
  • \$\begingroup\$ Can you post the broken code? You should not be passing in a reference to the Object explicitly as you are. I suspect that you were missing the this for example this._rootElement.style.top. \$\endgroup\$
    – JohnMark13
    Commented Sep 4, 2013 at 11:53
  • \$\begingroup\$ OK, did you update the AdfDhtmlSimpleFloat prototype before trying to call the function? Here is a super simple example jsfiddle.net/yvJfw/2, comment and uncomment the calls to updateElem to see. \$\endgroup\$
    – JohnMark13
    Commented Sep 4, 2013 at 14:27
  • \$\begingroup\$ Yes, the function is defined, and gets called properly. \$\endgroup\$ Commented Sep 5, 2013 at 5:44

1 Answer 1

1
\$\begingroup\$

The problem is that this._slideIn refers to a function, not a method invocation. In your third code sample, changing your last line to

var self = this;
setTimeout(function() { self._slideIn(componentId) }, 20);

should be sufficient. You have to capture this in the closure that you pass to setTimeout(), because when the code runs later, this will refer to something else in that execution context.

\$\endgroup\$
2
  • \$\begingroup\$ This did it. Could you please elaborate on this? I debugged it and don't understand it. Now at every call, this references the AdfDhtmlSimpleFloat object. Why is this so? \$\endgroup\$ Commented Sep 5, 2013 at 9:23
  • \$\begingroup\$ You would be better off taking this up on StackOverflow. Here's the background and a reformulation of your question. \$\endgroup\$ Commented Sep 5, 2013 at 9:46

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.