Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9269023
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 18, 20262026-06-18T15:00:24+00:00 2026-06-18T15:00:24+00:00

I’m struggling with managing dynamically built event handlers in javascript. In several places, I

  • 0

I’m struggling with managing dynamically built event handlers in javascript.

In several places, I build forms, or controls in which specific events (mainly mouseovers, mouse-outs, clicks) need to be handled.

The trick is that in a significant number of cases, the event handler itself needs to incorporate data that is either generated by, or is passed-into the function that is building the form or control.

As such, I’ve been using “eval()” to construct the events and incorporate the appropriate data, and this has worked somewhat well.

The problem is I keep seeing/hearing things like “You should never use eval()!” as well as a couple of increasingly ugly implementations where my dynamically-built event handler needs to dynamically build other event handlers and the nested evals are pretty obtuse (to put it mildly).

So I’m here, asking if someone can please show me the better way (native javascript only please, I’m not implementing any third-party libraries!).

Here’s a crude example to illustrate what I’m talking about:

function CreateInput(controlName,type,activeStyle,dormantStyle,whenClicked)
{
    var inp = document.createElement('input');
    inp.id = controlName;
    inp.type = type;
    inp.style.cssText = dormantStyle;
    eval("inp.onfocus = function() { this.style.cssText = '" + activeStyle + "'; }");
    eval("inp.onblur = function() { this.style.cssText = '" + dormantStyle + "'; }");
    eval("inp.onclick = function() { " + whenClicked + "; }");
    return inp;
}

This function obviously would let me easily create lots of different INPUT tags and specify a number of unique attributes and event actions, with just a single function call for each. Again, this is an extremely simplified example, just to demonstrate what I’m talking about, in some cases with the project I’m on currently, the events can incorporate dozens of lines, they might even make dynamic ajax calls based on a passed parameter or other dynamically generated data. In more extreme cases I construct tables, whose individual rows/columns/cells may need to process events based on the dynamically generated contents of the handler, or the handler’s handler.

Initially, I had built functions like the above as so:

function CreateInput(controlName,type,activeStyle,dormantStyle,whenClicked)
{
    var inp = document.createElement('input');
    inp.id = controlName;
    inp.type = type;
    inp.style.cssText = dormantStyle;
    inp.onfocus = function() { this.style.cssText = activeStyle; };
    inp.onblur = function() { this.style.cssText = dormantStyle; };
    eval("inp.onclick = function() { " + whenClicked + "; }");
    return inp;
}

…but I found that whatever the last assigned value had been for “activeStyle”, and “dormantStyle” became the value used by all of the handlers thusly created (instead of each retaining its own unique set of styles, for example). That is what lead me to using eval() to “lock-in” the values of the variables when the function was created, but this has lead me into nightmares such as the following:

(This is a sample of one dynamically-built event-handler that I’m currently working on and which uses a nested eval() function):

    eval("input.onkeyup = function() { " +
            "InputParse(this,'ucwords'); " +
            "var tId = '" + myName + This.nodeName + "SearchTable" + uidNo + "'; " +
            "var table = document.getElementById(tId); " +
            "if (this.value.length>2) { " +
                "var val = (this.value.indexOf(',') >=0 ) ? this.value.substr(0,this.value.indexOf(',')) : this.value; " +
                "var search = Global.LoadData('?fn=citySearch&limit=3&value=' + encodeURI(val)); " +
                "if (table) { " +
                    "while (table.rows.length>0) { table.deleteRow(0); } " +
                    "table.style.display='block'; " +
                "} else { " +
                    "table = document.createElement('table'); " +
                    "table.id = tId; " +
                    "ApplyStyleString('" + baseStyle + ";position=absolute;top=20px;left=0px;display=block;border=1px solid black;backgroundColor=rgba(224,224,224,0.90);zIndex=1000;',table); " +
                    "var div = document.getElementById('" + divName + "'); " +
                    "if (div) { div.appendChild(table); } " +
                "} " +
                "if (search.rowCount()>0) { " +
                    "for (var i=0; i<search.rowCount(); i++) { " +
                        "var tr = document.createElement('tr'); " +
                        "tr.id = 'SearchRow' + i + '" + uidNo + "'; " +
                        "tr.onmouseover = function() { ApplyStyleString('cursor=pointer;color=yellow;backgroundColor=rgba(40,40,40,0.90);',this); }; " +
                        "tr.onmouseout = function() { ApplyStyleString('cursor=default;color=black;backgroundColor=rgba(224,224,224,0.90);',this); }; " +
                        "eval(\"tr.onclick = function() { " +
                            "function set(id,value) { " +
                                "var o = document.getElementById(id); " +
                                "if (o && o.value) { o.value = value; } else { alert('Could not find ' + id); } " +
                            "} " +
                            "set('" + myName + This.nodeName + "CityId" + uidNo + "','\" + search.id(i)+ \"'); " +
                            "set('" + myName + This.nodeName + "ProvId" + uidNo + "','\" + search.provId(i)+ \"'); " +
                            "set('" + myName + This.nodeName + "CountryId" + uidNo + "','\" + search.countryId(i) + \"'); " +
                            "set('" + input.id + "','\" + search.name(i)+ \"'); " +
                            "}\"); " +
                        "var td = document.createElement('td'); " +
                        "var re = new RegExp('('+val+')', 'gi'); " +
                        "td.innerHTML = search.name(i).replace(re,'<span style=\"font-weight:bold;\">$1</span>') + ', ' + search.provinceName(i) + ', ' + search.countryName(i); " +
                        "tr.appendChild(td); " +
                        "table.appendChild(tr); " +
                    "} " +
                "} else { " +
                    "var tr = document.createElement('tr'); " +
                    "var td = document.createElement('td'); " +
                    "td.innerHTML = 'No matches found...';" +
                    "tr.appendChild(td); " +
                    "table.appendChild(tr); " +
                "} " +
            "} else { " +
                "if (table) table.style.display = 'none'; " +
            "} " +
        "} ");

Currently, I’m having problems getting the nested eval() to bind the “.onclick” event to the table-row, and, as you can see, figuring out the code is getting pretty hairy (debugging too, for all the known reasons)… So, I’d really appreciate it if someone could point me in the direction of being able to accomplish these same goals while avoiding the dreaded use of the “eval()” statement!

Thanks!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-18T15:00:25+00:00Added an answer on June 18, 2026 at 3:00 pm

    And this, among many other reasons, is why you should never use eval. (What if those values you’re “baking” in contain quotes? Oops.) And more generally, try to figure out why the right way doesn’t work instead of beating the wrong way into submission. 🙂

    Also, it’s not a good idea to assign to on* attributes; they don’t scale particularly well. The new hotness is to use element.addEventListener, which allows multiple handlers for the same event. (For older IE, you need attachEvent. This kind of IE nonsense is the primary reason we started using libraries like jQuery in the first place.)


    The code you pasted, which uses closures, should work just fine. The part you didn’t include is that you must have been doing this in a loop.

    JavaScript variables are function-scoped, not block-scoped, so when you do this:

    var callbacks = [];
    for (var i = 0; i < 10; i++) {
        callbacks.push(function() { alert(i) });
    }
    
    for (var index in callbacks) {
        callbacks[index]();
    }
    

    …you’ll get 9 ten times. Each run of the loop creates a function that closes over the same variable i, and then on the next iteration, the value of i changes.

    What you want is a factory function: either inline or independently.

    for (var i = 0; i < 10; i++) {
        (function(i) {
            callbacks.push(function() { alert(i) });
        })(i);
    }
    

    This creates a separate function and executes it immediately. The i inside the function is a different variable each time (because it’s scoped to the function), so this effectively captures the value of the outer i and ignores any further changes to it.

    You can break this out explicitly:

    function make_function(i) {
        return function() { alert(i) };
    }
    
    // ...
    
    for (var i = 0; i < 10; i++) {
        callbacks.push(make_function(i));
    }
    

    Exactly the same thing, but with the function defined independently rather than inline.

    This has come up before, but it’s a little tricky to spot what’s causing the surprise.


    Even your “right way” code still uses strings for the contents of functions or styles. I would pass that click behavior as a function, and I would use classes instead of embedding chunks of CSS in my JavaScript. (I doubt I’d add an ID to every single input, either.)

    So I’d write something like this:

    function create_input(id, type, active_class, onclick) {
        var inp = document.createElement('input');
        inp.id = id;
        inp.type = type;
        inp.addEventListener('focus', function() {
            this.className = active_class;
        });
        inp.addEventListener('blur', function() {
            this.className = '';
        });
        inp.addEventListener('click', onclick);
    
        return inp;
    }
    
    // Called as:
    var textbox = create_input('unique-id', 'text', 'focused', function() { alert("hi!") });
    

    This has some problems still: it doesn’t work in older IE, and it will remove any class names you try to add later. Which is why jQuery is popular:

    function create_input(id, type, active_class, onclick) {
        var inp = $('<input>', { id: id, type: type });
        inp.on('focus', function() {
            $(this).addClass(active_class);
        });
        inp.on('blur', function() {
            $(this).removeClass(active_class);
        });
    
        inp.on('click', onclick);
    
        return inp;
    }
    

    Of course, even most of this is unnecessary—you can just use the :focus CSS selector, and not bother with focus and blur events at all!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I used javascript for loading a picture on my website depending on which small
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I am trying to understand how to use SyndicationItem to display feed which is
I have a small JavaScript validation script that validates inputs based on Regex. I
I am trying to render a haml file in a javascript response like so:
I would like to run a str_replace or preg_replace which looks for certain words
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
We're building an app, our first using Rails 3, and we're having to build
I have an autohotkey script which looks up a word in a bilingual dictionary
I have an array which has BIG numbers and small numbers in it. I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.