Question

I am working on a script that should be able to dynamically load content in multiple predefined DIVs in the topbar of my webpage.

Within the Topbar Object, Ribbon is an object that holds the functions used to manipulate one of the DIVs in the Topbar, some of which (all at the moment) are inherited from Container, of which Ribbon is an instance.

The functions MPP_Topbar.Ribbon.clear() and MPP_Topbar.Ribbon.load('default.xml') work as intended. However, the callback function MPP_Topbar.Ribbon.insert(), which is called from the ajaxGet() function once the xmlhttprequest is completed, does not do what it's supposed to do. Somehow this within the insert class method suddenly points to window instead of its parent object Ribbon.

Is there any way for me to reference Ribbon within the insert method?


The Topbar script:

MPP_Topbar = {};

MPP_Topbar.Container = function(){};

MPP_Topbar.Container.prototype.clear = function(){
    var element = this.element;
    while (element.firstChild) {
        element.removeChild(element.firstChild);
    }
};

MPP_Topbar.Container.prototype.load = function(page){
    this.clear();
    ajaxGet(page, this.insert);
    console.log('loading');
};

MPP_Topbar.Container.prototype.insert = function(content){
    console.log(this);
    this.element.innerHTML = content;
    console.log('inserted');
};

MPP_Topbar.Ribbon = new MPP_Topbar.Container;

MPP_Topbar.Ribbon.element = document.getElementById('THERIBBON');

The function used for the AJAX request:

function ajaxGet(file, callback, postdata, async){
    async = ((async == true || async === undefined) ? true : false);
    var xmlhttp;
    if (window.XMLHttpRequest){
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    }
    else{
        // code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    if(async){
        xmlhttp.onreadystatechange=function(){
            if (xmlhttp.readyState==4 && xmlhttp.status==200){
                callback(xmlhttp.responseText);
            }
        }
    }
    if(postdata){
        xmlhttp.open("POST", file, async);
        xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    }else{xmlhttp.open("GET", file, async);}
    xmlhttp.send();
}
Was it helpful?

Solution

You need to create a bound version of the "insert" function:

ajaxGet(page, this.insert.bind(this));

Without that step, the "insert" function will be invoked such that this refers to the global (window) object. The value of this has nothing to do with how or where a function is declared, and everything to do with how the function is invoked. The .bind() method returns a function that explicitly arranges for this to be bound to the object you pass as a parameter when the desired function is called.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top