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