0

I know it sounds stupid, but i have no idea how to call my function from "onclick" function?

I made own class and what i wanna do is to call my function inside a class. I have tried various stuff inside that onclick function:

  • function(){this.getWidth()}
  • this.getWidth()
  • Test.getWidth()

function Datagrid(_parent, _data) { this.table = []; this.parent = $("#"+_parent)[0] ? $("#"+_parent) : ($("."+_parent)[0] ? $("."+_parent) : ($(+_parent)[0] ? $(_parent) : null)); this.data = _data;

this.Datagrid = function(parent,data)
{
    this.setParent(parent);
    if(data != null)
        this.setData(data);
    return this;
}


this.setParent = function(parent)
{
    return this.parent = $("#"+parent)[0] ? $("#"+parent) : ($("."+parent)[0] ? $("."+parent) : ($(+parent)[0] ? $(parent) : null));
}

this.getParent = function()
{return this.parent;}

this.setData = function(data)
{this.data = data;}

this.buildTable = function()
{
    var dtTbl = [];
    dtTbl.push('<table class="TimeSheetmainTable" cellpadding="10" cellspacing="0" border="0">');

    var style;

    //Header//////////////////////
    dtTbl.push('<tr class="header">');
    for (var cell in this.data.row[0].cell) {
        dtTbl.push('<td>' + this.data.row[0].cell[cell].id + '</td>');
    }
    dtTbl.push('</tr>');
    //Content//////////////////////
    for(var r in this.data.row)
    {
        if (r % 2 == 0) { style = 'class="r1" onmouseover="this.className=\'hover\'"  onmouseout="this.className=\'r1\'"'; }
        else { style = 'class="r2" onmouseover="this.className=\'hover\'"  onmouseout="this.className=\'r2\'"'; }

        dtTbl.push('<tr ' + style + ' >');
        for(var c in this.data.row[r].cell)
        {
            dtTbl.push('<td alt="' + this.data.row[r].cell[c].id + '">' + this.data.row[r].cell[c].value + '</td>');
        }
        dtTbl.push('</tr>');
    }
    //Footer//////////////////////
    dtTbl.push('<tr class="footer">');
    for (var cell in this.data.row[0].cell) {
        dtTbl.push('<td>&nbsp;</td>');
    }
    dtTbl.push('</tr></table>');

    this.parent.html(dtTbl.join(''));
}

this.buildTableDiv = function()
{
    var tableString = [];
    //Header//////////////////////
    tableString.push('<div class="container"><div class="header"><table><tr id="header">');
    for (var cell in this.data.row[0].cell) {
        tableString.push('<td>' + this.data.row[0].cell[cell].id + '</td>');
    }
    tableString.push('</tr></table></div>');
    //Content//////////////////////
    tableString.push('<div class="content"><table>');
    var TD1 = new Object();
    var TD2 = new Object();

    for(var r in this.data.row)
    {
        if (r % 2 == 0) { style = 'class="r1" onmouseover="this.className=\'hover\'"  onmouseout="this.className=\'r1\'"'; }
        else { style = 'class="r2" onmouseover="this.className=\'hover\'"  onmouseout="this.className=\'r2\'"'; }

        for(var c in this.data.row[r].cell)
        {
            if(c == 0)
            {   if(TD1.value != this.data.row[r].cell[c].value){
                    TD1.value = this.data.row[r].cell[c].value;
                    TD1.show = true;
                }
                else
                    TD1.show = false;
            }
            if(c == 1)
            {   if(TD2.value != this.data.row[r].cell[c].value){
                    TD2.value = this.data.row[r].cell[c].value;
                    TD2.show = true;
                }
                else
                    TD2.show = false;
            }   
            if(TD1.show && c == 0){//First line
                tableString.push('<tr id="content" ' + style + ' >');
                tableString.push('<td alt="' + this.data.row[r].cell[c].id + '"><input type="button" class="arrow_down" /> ' + this.data.row[r].cell[c].value + '</td>');
                for(var c = 0; c < this.data.row[r].cell.length - 1; c++)
                {
                    tableString.push('<td>&nbsp</td>');
                }
                tableString.push('</tr>');
            }
            else if(TD2.show && c == 1)//Second line
            {
                tableString.push('<tr id="content" ' + style + ' >');
                tableString.push('<td>&nbsp;</td><td alt="' + this.data.row[r].cell[c].id + '">' + this.data.row[r].cell[c].value + '</td>');
                for(var c = 0; c < this.data.row[r].cell.length - 2; c++)
                {
                    tableString.push('<td>&nbsp</td>');
                }
                tableString.push('</tr><tr id="content" ' + style + ' ><td>&nbsp;</td><td>&nbsp;</td>');
            }
            else if(!TD2.show && c == 1)//third line (distincts second cells name)
            {
                tableString.push('<tr id="content" ' + style + ' >');
                tableString.push('<td>&nbsp;</td><td alt="' + this.data.row[r].cell[c].id + '">&nbsp;</td>');
            }
            else if(c > 1)//Rest filling (not ordered stuff)
            {
                tableString.push('<td alt="' + this.data.row[r].cell[c].id + '">' + this.data.row[r].cell[c].value.replace("","&nbsp;") + '</td>');
            }
        }
        tableString.push('</tr>');
        // $(".arrow_down").children(":nth-child(1)").click(function(){alert("test");});
    }
    tableString.push('</table></div>');
    //Footer//////////////////////
    tableString.push('<div class="footer"><table><tr id="footer">');
    for (var cell in this.data.row[0].cell) {
        tableString.push('<td>&nbsp;</td>');
    }
    tableString.push('</tr></table></div></div>');

    this.parent.html(tableString.join(''));

    // Setting width to all cells
    for (var i in this.data.row[0].cell)
    {
        cell = parseInt(i)+1;
        var h = this.parent.children(":first").children(".header").children("table").children("tbody").children("tr").children(":nth-child("+ cell +")").width();
        var c = this.parent.children(":first").children(".content").children("table").children("tbody").children("tr").children(":nth-child("+ cell +")").width();
        var f = this.parent.children(":first").children(".footer").children("table").children("tbody").children("tr").children(":nth-child("+ cell +")").width();
        var width = h > c ? h : (c > f ? c : f);

        this.parent.children(":first").children(".header").children("table").children("tbody").children("tr").children(":nth-child("+ cell +")").width(width);
        this.parent.children(":first").children(".content").children("table").children("tbody").children("tr").children(":nth-child("+ cell +")").width(width);
        this.parent.children(":first").children(".footer").children("table").children("tbody").children("tr").children(":nth-child("+ cell +")").width(width);
    }
    // this.activateScroller(0);
}

this.getScrollerWidth = function()
{
    var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
     // Append our div, do our calculation and then remove it 
    $('body').append(div); 
    var w1 = $('div', div).innerWidth(); 
    div.css('overflow-y', 'scroll'); 
    var w2 = $('div', div).innerWidth(); 
    $(div).remove(); 
    return (w1 - w2); 
}

this.activateScroller = function(value)
{
    var d = [];
    d.push('<div style="height: ' + this.parent.children(":first").children(".content").height() + '; width:20px; background:#FFF"><div style="background:#333; height:200">&nbsp;</div></div>');

    this.parent.children(":first").children(".content").scrollTop(value);
}

expandParent = function()
{
    alert(this.parent);
}

};

i am kinda makig datagrid based on javascript. i am not allowed to use jQuery UI. My datagrid is made from tables. now i try to add a button inside a td element like User Name The problem is that i cant access my function inside my class without making instance. is it even possible to do that without making an instance?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Painkiller
  • 109
  • 1
  • 1
  • 10
  • Can you please elaborate what do you want to do?i mean what output do you expect.. – Heena Hussain Nov 19 '12 at 12:26
  • 1
    See this answer to explain how `this` works in javascript: http://stackoverflow.com/questions/13441307/how-does-the-this-keyword-in-javascript-act-within-an-object-literal/13441628#13441628 – slebetman Nov 19 '12 at 14:13

1 Answers1

1

Once your html is generated using your generateHTML function, the handler for onclick on div looses context of what "this" is. To be more specific, this in onclick handler for div refers to that div node in DOM.

To access getWidth method you have to make it available to global context or (better solution) do something like this:

// new version of your generateHTML function
this.generateHTML() {
   var str = [];
   str.push('<div><input type="button" value="button"/></div>');
   var that = this;
   $("#testDiv").append(str.join('')).find('button:first').click(function() {that.getWidth()});
}

EDIT: To further explain how code above works, here's simplified example with comments.

​​Test = function() {    
    this.generate = function() {
        var newnode = $('<button>click me</button>');        
        $("body").append(newnode);
        // "cache" this in a variable - that variable will be usable in event handler
        var that = this;
        // write event handler function here - it will have access to your methods by using "that" variable
        newnode.click(function(e) {
            // here this refers to button not Test class
            // so we have to "reach" to outer context to gain access to all methods from Test
            that.doSomething('learn');
        })
    }
    this.doSomething = function(x) {
        alert('do it: '+x);            
    }
}

// initialize part
// make instance of Test "class"
t = new Test();
// generate the button (clicking on a button will essentialy fire Test.doSomething function in a context of "t"
t.generate();
WTK
  • 16,583
  • 6
  • 35
  • 45
  • `$(".arrow_down").click(function(){expandParent();});` i tried that call but it is not what i want. if i use your methot, i will have to exclude my function from my class making it a global function. it ok, but i want to use variables from my class, and i using them in global function i will have to make an instance of my class in that function :( hope made myself clear :D thanks anyway! – Painkiller Nov 19 '12 at 12:55
  • You do realize that your Datagrid is a function and need to be instantiate using `new` keyword, to serve as instance? That's on side note. As to using that in event handlers for elements you're creating. Once the event is fired `this` in that event handler is already associated with different object than your class. To overcome that, you need (like I've illustrated above) *cache* reference to your class in variable in outer scope. Then in your event handler you can refer to any method in your class using: `that` variable. For example do `that.setData(...)` – WTK Nov 19 '12 at 13:09
  • Is there any way to make that cakk inside a function? Or should i change function FunctionName(){} to var FunctionName = {} ? Thanks – Painkiller Nov 19 '12 at 13:15
  • You have to be more specific, what call (assumed) inside which function? – WTK Nov 19 '12 at 13:35
  • what i ment is should i change the structure of my class like above. if i will use `var myclass = { this.bla, functionBla: function(){blabla...} ` in that case i can refer on fy function like `className.functionName` but can i make the class unique (instance) ? (like in my example with a word new) – Painkiller Nov 19 '12 at 13:50
  • I've update my answer with simplified example of structure you may use. – WTK Nov 19 '12 at 14:06