最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

function - How do I run an object's method onEvent in javascript? - Stack Overflow

programmeradmin2浏览0评论

I just started using javascript and I'm missing something important in my knowledge. I was hoping you could help me fill in the gap.

So the script I'm trying to run is suppose to count the characters in a text field, and update a paragraph to tell the user how many characters they have typed. I have an object called charCounter. sourceId is the id of the text area to count characters in. statusId is the id of the paragraph to update everytime a key is pressed.

function charCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
}

There is one method called updateAll. It updates the count of characters and updates the paragraph.

charCounter.prototype.updateAll = function() {
    //get the character count;
    //change the paragraph;
}

I have a start function that is called when the window loads.

function start() {
    //This is the problem
    document.getElementbyId('mytextfield').onkeydown = myCounter.updateAll;
    document.getElementbyId('mytextfield').onkeyup = myCounter.updateAll;
}

myCounter = new charCounter("mytextfield","charcount");
window.onload = start;

The above code is the problem. Why in the world can't I call the myCounter.updateAll method when the event is fired? This is really confusing to me. I understand that if you call a method likeThis() you'll get a value from the function. If you call it likeThis you are getting a pointer to a function. I'm pointing my event to a function. I've also tried calling the function straight up and it works just fine, but it will not work when the event is fired.

What am I missing?


Thanks for all the answers. Here's three different implementations.

Implementation 1

function CharCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
};
    CharCounter.prototype.updateAll = function() {
        this.count = document.getElementById(this.sourceId).value.length;
        document.getElementById(this.statusId).innerHTML = "There are "+this.count+" charactors";
    };

function start() {
    myCharCounter.updateAll();
    document.getElementById('mytextfield').onkeyup = function() { myCharCounter.updateAll(); };
    document.getElementById('mytextfield').onkeydown = function() { myCharCounter.updateAll(); };   
};

myCharCounter = new CharCounter('mytextfield','charcount');
window.onload = start;

Implementation 2

function CharCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
};
    CharCounter.prototype.updateAll = function() {
        this.count = document.getElementById(this.sourceId).value.length;
        document.getElementById(this.statusId).innerHTML = "There are "+ this.count+" charactors";
    };
    CharCounter.prototype.start = function() {
        var instance = this;
        instance.updateAll();

        document.getElementById(this.sourceId).onkeyup = function() {
            instance.updateAll();
        };
        document.getElementById(this.sourceId).onkeydown = function() {
            instance.updateAll();
        };
    };

window.onload = function() {
    var myCounter = new CharCounter("mytextfield","charcount");
    myCounter.start();
};

Implementation 3

function CharCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
};
    CharCounter.prototype.updateAll = function() {
        this.count = document.getElementById(this.sourceId).value.length;
        document.getElementById(this.statusId).innerHTML = "There are "+this.count+" charactors";
    };

function bind(funcToCall, desiredThisValue) {
    return function() { funcToCall.apply(desiredThisValue); };
};  

function start() {
    myCharCounter.updateAll();
    document.getElementById('mytextfield').onkeyup = bind(myCharCounter.updateAll,    myCharCounter);
    document.getElementById('mytextfield').onkeydown = bind(myCharCounter.updateAll, myCharCounter);
};

myCharCounter = new CharCounter('mytextfield','charcount');
window.onload = start;

I just started using javascript and I'm missing something important in my knowledge. I was hoping you could help me fill in the gap.

So the script I'm trying to run is suppose to count the characters in a text field, and update a paragraph to tell the user how many characters they have typed. I have an object called charCounter. sourceId is the id of the text area to count characters in. statusId is the id of the paragraph to update everytime a key is pressed.

function charCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
}

There is one method called updateAll. It updates the count of characters and updates the paragraph.

charCounter.prototype.updateAll = function() {
    //get the character count;
    //change the paragraph;
}

I have a start function that is called when the window loads.

function start() {
    //This is the problem
    document.getElementbyId('mytextfield').onkeydown = myCounter.updateAll;
    document.getElementbyId('mytextfield').onkeyup = myCounter.updateAll;
}

myCounter = new charCounter("mytextfield","charcount");
window.onload = start;

The above code is the problem. Why in the world can't I call the myCounter.updateAll method when the event is fired? This is really confusing to me. I understand that if you call a method likeThis() you'll get a value from the function. If you call it likeThis you are getting a pointer to a function. I'm pointing my event to a function. I've also tried calling the function straight up and it works just fine, but it will not work when the event is fired.

What am I missing?


Thanks for all the answers. Here's three different implementations.

Implementation 1

function CharCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
};
    CharCounter.prototype.updateAll = function() {
        this.count = document.getElementById(this.sourceId).value.length;
        document.getElementById(this.statusId).innerHTML = "There are "+this.count+" charactors";
    };

function start() {
    myCharCounter.updateAll();
    document.getElementById('mytextfield').onkeyup = function() { myCharCounter.updateAll(); };
    document.getElementById('mytextfield').onkeydown = function() { myCharCounter.updateAll(); };   
};

myCharCounter = new CharCounter('mytextfield','charcount');
window.onload = start;

Implementation 2

function CharCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
};
    CharCounter.prototype.updateAll = function() {
        this.count = document.getElementById(this.sourceId).value.length;
        document.getElementById(this.statusId).innerHTML = "There are "+ this.count+" charactors";
    };
    CharCounter.prototype.start = function() {
        var instance = this;
        instance.updateAll();

        document.getElementById(this.sourceId).onkeyup = function() {
            instance.updateAll();
        };
        document.getElementById(this.sourceId).onkeydown = function() {
            instance.updateAll();
        };
    };

window.onload = function() {
    var myCounter = new CharCounter("mytextfield","charcount");
    myCounter.start();
};

Implementation 3

function CharCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
};
    CharCounter.prototype.updateAll = function() {
        this.count = document.getElementById(this.sourceId).value.length;
        document.getElementById(this.statusId).innerHTML = "There are "+this.count+" charactors";
    };

function bind(funcToCall, desiredThisValue) {
    return function() { funcToCall.apply(desiredThisValue); };
};  

function start() {
    myCharCounter.updateAll();
    document.getElementById('mytextfield').onkeyup = bind(myCharCounter.updateAll,    myCharCounter);
    document.getElementById('mytextfield').onkeydown = bind(myCharCounter.updateAll, myCharCounter);
};

myCharCounter = new CharCounter('mytextfield','charcount');
window.onload = start;
Share Improve this question edited Oct 1, 2009 at 21:26 user182666 asked Oct 1, 2009 at 18:25 user182666user182666 1593 silver badges9 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 2

I think you are having problems accessing your instance members on the updateAll function, since you are using it as an event handler, the context (the this keyword) is the DOM element that triggered the event, not your CharCounter object instance.

You could do something like this:

function CharCounter(sourceId, statusId) {
    this.sourceId = sourceId;
    this.statusId = statusId;
    this.count = 0;
}

CharCounter.prototype.updateAll = function() {
  var text = document.getElementById(this.sourceId).value;
  document.getElementById(this.statusId).innerHTML = text.length;
};

CharCounter.prototype.start = function() {
  // event binding
  var instance = this; // store the current context
  document.getElementById(this.sourceId).onkeyup = function () {
    instance.updateAll(); // use 'instance' because in event handlers
                          // the 'this' keyword refers to the DOM element.
  }; 
}

window.onload = function () {
  var myCharCounter = new CharCounter('textarea1', 'status');
  myCharCounter.start();
};

Check the above example running here.

The expression "myCounter.updateAll" merely returns a reference to the function object bound to "updateAll". There's nothing special about that reference - specifically, nothing "remembers" that the reference came from a property of your "myCounter" object.

You can write a function that takes a function as an argument and returns a new function that's built specifically to run your function with a specific object as the "this" pointer. Lots of libraries have a routine like this; see for example the "functional.js" library and its "bind" function. Here's a real simple version:

function bind(funcToCall, desiredThisValue) {
  return function() { funcToCall.apply(desiredThisValue); };
}

Now you can write:

document.getElementById('myTextField').onkeydown = bind(myCounter.updateAll, myCounter);

You can:

function start() {
    //This is the problem
    document.getElementbyId('mytextfield').onkeydown = function() { myCounter.updateAll(); };
    document.getElementbyId('mytextfield').onkeyup = function() { myCounter.updateAll(); };
}

In ASP.Net Ajax you can use

Function.createDelegate(myObject, myFunction); 

I want to do something like this but simpler. The idea is to have the user click on bolded text and have a text field appear where they can change all the values of a role-playing character. Then when the value is changed, have the text field disappear again replaced by the updated bolded text value. I can do this already using an annoying text box alert. But I would rather have something similar to this below to replace all that. I have searched for months and CMS is the closest to answering my question in the simplest way with a full html example. Nobody else on the net could.

So my question is, how do I do this? I have multiple objects(characters) and need this.elementId to make this work.

I've modified this example but it breaks if I try to add to it.


html>
head>
title>Sandbox
/head>
body>
input id="textarea1" size=10 type=text>

script>
function CharCounter(sourceId, statusId)
 {this.sourceId=sourceId;
  this.statusId=statusId;
  this.count=0;
 }
CharCounter.prototype.updateAll=function() 
 {text=document.getElementById(this.sourceId).value 
  document.getElementById(this.statusId).innerHTML=text
 }
CharCounter.prototype.start=function()
 {instance=this 
  document.getElementById(this.sourceId).onkeyup=function ()
   {instance.updateAll()} 
 }
window.onload=function ()
 {myCharCounter=new CharCounter('textarea1', 'status')
  myCharCounter.start()
 }
/script>
/body>
/html>

发布评论

评论列表(0)

  1. 暂无评论