Pager & Event Handlers

Antranig Basman antranig.basman at colorado.edu
Thu Feb 17 07:30:37 UTC 2011


Hi Eric - thanks for this question, which I imagine is something comes up a lot. I guess it's best to start 
with a few physical and philosophical points.... firstly, that the action of the renderer is to slap a large 
markup string which it has carefully pre-formed, into the "innerHTML" of a DOM node. This is for performance 
reasons, amongst others - even in modern browsers, long sequences of primitive DOM manipulations become a 
serious performance risk, because of the global locks which each operation must take out. So, there is no 
possibility for any DOM state and event handlers to survive this process since there is no "stripping" 
process - the entire block of DOM state is destroyed and recreated.

This puts a premium on trying to work together with the renderer rather than trying to pick up its products 
after the fact (although the latter approach could probably be made to work). Unfortunately the Pager is not 
a fully baked component and doesn't expose quite all the workflow that you might be interested in - however, 
I think you are at least partially in luck that the piece that you are interested probably exposes enough to 
help you. In particular, the "fluid.pager.renderedPageList" component fires an event

                 events.onRenderPageLinks.fire(pageTree, newModel);

of which the first argument is actually the renderer's component tree for the upcoming operation of 
rendering the page links area for the pager. It may not be perfectly obvious from the documentation, but 
actually the implementor is warmly invited to process and modify this first argument (in place) to add any 
additional material they require to the upcoming rendering activity. The "page links tooltip" component 
actually uses this method in order to decorate the page links area with tooltips describing the ranges 
covered by each of the pages - but there is no reason that you should add completely new components for 
example dealing with the paycheck amount etc. (of course adding suitable extra markup to the template for 
this area - it may require a bit of "fiddling" to make this interact nicely with the rather rigid hierarchy 
required by the HTML table layout - give Jen a shout since she has done this and knows how).

Your second point is interesting and highlights an important design point underlying the Fluid components. 
In general, we consider using the DOM itself as a source and repository of state (as in the case of your 
checkbox) to be somewhat dangerous and undesirable - it takes a long time to train ourselves and our users 
out of this habit because it is so prevalent in client-side programming. You will be familiar with the MVC 
pattern from the server-side and we believe that it isn't just for Christmas... all of the components in the 
Fluid set (except for those designed right at the start of the project and not yet reformed) keep a 
well-defined "model" as a top-level member, holding the pure state which they will use for their rendering. 
It would be a great exercise to convert your piece of functionality you describe into a Fluid component of 
this type, and arrange to attach a listener from it to the event handler I mention above. Here are some 
helpful links to get you started  -

http://wiki.fluidproject.org/display/fluid/Fluid+Component+API
http://wiki.fluidproject.org/display/fluid/Getting+Started+Creating+Infusion+Components
http://wiki.fluidproject.org/display/fluid/How+to+Create+a+Fluid+Component
http://wiki.fluidproject.org/display/fluid/Component+Model+Interactions+and+API (this one very old)
http://wiki.fluidproject.org/display/fluid/How+to+Define+a+Unit (the word "Unit" is no longer used, we 
simply say "component" even though it is ambiguous)

Give us a shout on-list or in IRC if you need a hand - it isn't as daunting as it looks

On 16/02/2011 19:08, Eric Dalquist wrote:
> I keep running into this same problem and am hoping someone has a suggestion or two. The problem is with the
> pager it appears to strip all state and event handlers from all elements within the pager div every time it
> re-renders. In most cases I've been able to work around it but in this case I'm not sure what to do. Our UI
> design calls for two table header rows, one with a checkbox that lets the user toggle if their paycheck
> amount is visible and a second with the actual table headers. I attach a jQuery event handler to the
> checkbox using the live() function to deal with the fact that any time the user sorts or pages normal event
> handlers on the input are removed. The bigger problem is the state of the checkbox is also reset. If the
> user checks the box then pages or sorts the box unchecks. Is there some way to get the renderer to not strip
> state (and even better event handlers) from elements when it is redrawing the page? Especially elements like
> this which have no rsf:id attributes and have no real need to be touched by the renderer code.
>
> Another thing that would be useful that wasn't obvious from the docs is a postRender() callback. That way I
> could at least re-attach event handlers to all of the new elements when paging or sorting happened instead
> of using the live() feature of jQuery.
>
>
> <div class="fl-pager">
> <div class="fl-container-flex hrs-pager-table-data fl-pager-data">
> <table class="hrs-table">
> <thead>
> <tr>
> <th colspan="3" class="hrs-earnings-ammount-toggle">
> <form action="#">
> <input id="Pluto_35_n40_16_n40_hrs-earnings-ammount-toggle" name="hrs-earnings-ammount-toggle"
> type="checkbox"/>
> <label for="Pluto_35_n40_16_n40_hrs-earnings-ammount-toggle"> Show earnings dollar amounts</label>
> </form>
> </th>
> </tr>
> <tr rsf:id="header:">
> <th class="flc-pager-sort-header" rsf:id="paid"><a href="javascript:;">Paid</a></th>
> <th class="flc-pager-sort-header" rsf:id="earned"><a href="javascript:;">Earned</a></th>
> <th class="flc-pager-sort-header" rsf:id="ammount"><a href="javascript:;">Ammount</a></th>
> </tr>
> </thead>
> <tbody>
>
> <tr rsf:id="row:" class="hrs-clickable">
> <td class="hrs-data-text"><a class="todo" href="#" target="_blank" rsf:id="paid"></a></td>
> <td class="hrs-data-text"><a class="todo" href="#" target="_blank" rsf:id="earned"></a></td>
> <td class="hrs-data-number"><a class="todo hrs-earning-ammount" href="#" target="_blank"
> rsf:id="ammount"></a></td>
> </tr>
> </tbody>
> </table>
> </div>
> </div>
>
>
> Script:
> $("#Pluto_35_n40_16_n40_hrs-earnings-ammount-toggle").change(function() {
> if ($(this).is(':checked')) {
> $("#Pluto_35_n40_16_n40_hrs-payroll-information table.hrs-table a.hrs-earning-ammount").show();
> }
> else {
> $("#Pluto_35_n40_16_n40_hrs-payroll-information table.hrs-table a.hrs-earning-ammount").hide();
> }
> });
>



More information about the fluid-work mailing list