开发者

Event.observe inefficient with prototype Javascript, alternatives?

We have a table with a lot of checkboxes, onchange of a checkbox we want to call some Javascript. We use someth开发者_运维百科ing similar to this snippet:

addEventObserver(elementId){
        // ($= means 'ends with') this is required for elementIds which are in a table and get prepended with some id
        $$('[id$=:'+elementId+']').each(function(e) {
            Event.observe(e, 'change', function(event) {
                submitAction(something);
            });
        });
}

So below an input checkbox we add a Javascript function call:

<input type="checkbox" name="somename" id="somePrependedIdsomeId">    
<script type="text/javascript" language="javascript">
                    addEventObserver('someId');
                </script>

this works fine with our test environment settings. In production though we have tables with ~700 checkboxes and this makes the browser/cpu get stuck.

We use jsf


I would scrap adding an event listener to every single checkbox in favour of writing a single "smart" event handler attached to a container element. Here is a simple example:

var theDiv = document.getElementById("foo");
theDiv.onchange = function(e) {
    if (e.target.tagName.toLowerCase() == "input" 
          && e.target.type.toLowerCase() == "checkbox") {
        alert("do something");
    }
}

Demo: http://jsfiddle.net/xFC3A/

The onchange event is thus captured by the container div which is bubbles up to. The event attached to the div can test for the type of element that triggered the event (the source/target element depending on the browser) and react accordingly. Main advantages are:

  1. Only one event handler - no time wasted binding handlers to hundreds of elements.
  2. It will continue to work on dynamically added elements (via AJAX, JS etc.).

Read more about Event Delegation.

Some useful reference: http://www.quirksmode.org/js/events_properties.html


I'm not much of a Prototype jockey (much more of a jQuery guy), but generally speaking, any selector using an attribute selector is going to be slow. If you're running that selector on 700+ items, you're going to hit a massive slowdown for sure.

You're also using Prototype's each() method... could you re-write things to use a native javascript for() loop instead? Again, referring to jQuery here, but I've gotten INCREDIBLE performance gains by using native JS rather than library methods whenever possible. I've sped a web app by 20x by removing a bunch of jQuery .each() methods and replacing them with native for() loops.


I think Event Delegation should help you, simple attach die EventHandler to the Parent of all Checkboxes

$('container').observe("change", changeBy);

function changeBy(e){
                if (e.element().identify() != "container") {
            doChange(e.element());
        }
}

function doChange(elem){
  submitAction(something);
}

Markup:

<div id="container"> <input type="checkbox" > ... </div>

You doesn't need to do the foreach and you doesn't have hundreds of eventhandler, you simple have one EventHandler, this is pretty fast.


Prototype already provides event delegation by way of Event.on:

$('id_of_table').on('change', 'input[type=checkbox]', some_handler_function);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜