Jason Bennett's Developer Corner

 






Click to see the XML version of this web page.

>


View David Jason Bennett's profile on LinkedIn

 

 

A Little About Jason Bennett ...

I've had an interest in publishing technical articles and HELPFUL code for a few years.  I am (by trade and hobby) a developer who specializes in Oracle technologies and web based architectures.  I have been an employee of both TUSC and Oracle Corporation.  My intent here is to share my ideas and coding experiences with the developer community as a whole.  As with all developers some of my ideas are great and some of them are ....  well you know.  Anyway, I hope you find something here that will aid in your endeavor, or spark a new idea. 

I am more than happy to assist with technical issues and will even write a little code if need be. If you find something on the site that is really useful and you'd like to make a contribution (absolutely up to you and absolutely not required), just click the "Make a Donation" button on the left!

Good luck and good coding !




  Saturday, March 15, 2008


ADF Faces JavaScript Hack: How to Move a Generated Tag Event Handler

 

You may have noticed that ADF Faces generates some very specific JavaScript code for handling page level (tag level) events (onclick, onChange, onBlur, etc ...).  These event handlers "handle" all of those cool features such as "Partial Submit" and "Auto Submit".   Most of the time, we as developers (and users of ADF) have no direct control over where these framework generated event handlers are placed, or specific control over when they will fire.  The focus of this entry is on how to move a generated event handler from one event to another on the same tag.  For example:  Let's say that you want to implement a feature that will allow a user to type in an employee Id and then have the rest of the employee information (name, etc ..) auto populate. No problem, you just bind a method from a backing bean to a ValueChangeListener and turn on Auto Submit and you are done!  However, what if you also want to use a command link to implement an LOV dialog on the same data entry field and use the data (i.e. the employee id) to limit the results of the LOV?  Now you have a problem.  If you enter data in the employee id field, and then try to navigate to your LOV link, the value change event (onChange) fires before the LOV triggers and nullifies the LOV event.  The solution to the problem is obvious ... just change the triggering event from onChange to onKeyPress (for the auto population ... you would also need to add code to check for the triggering "Hot Key").  But wait ... that code was generated by ADF Faces.  We (the developers) have no direct control over where they place their code.  Now, the problem becomes slightly more challenging (or interesting).  The solution (one solution anyway ...) is to write a JavaScript function that will move it for you and leave the original code intact.  My version of the function looks like this:

 

function moveEventFunction(p_id,p_curr_event,p_new_event,conditionalFunc){

 

   /* Get instance of the tag we are modifying. */

   var formItem = document.getElementById(p_id);

 

   var eventFunc = null;

  

   /* Get text of target event handler code */

   var existingEventCode = formItem.attributes[p_curr_event].value;

 

   /* Only execute the move if the targeted event handler is populated */

   if (existingEventCode.length > 0){

  

      /* Convert text of existing event handler back into a working function */

      var existingFunction = new Function(existingEventCode);

  

      /* Create a function that will assign a new event handler to the desired item event.

       * This needs to be dynamic since we can only make a direct assignment under "normal"

       * circumstances.  Ex. node.onclick=  or node.onchange

       */

 

      var addNewEvent = new Function("node","eventfunc","node."+p_new_event+"=eventfunc;");

     

      /* We assign "nothing" to the existing event handler. This must be dynamic

       * for the same reason as the function above.

       */

 

      var removeExistingEvent = new Function("node","node."+p_curr_event+"='';");

  

      /* If a conditinal function (boolean function that can halt the event ...)

       * is provided, then wrap it around the existing code.  Otherwise, execute

       * the original handler under the new event.

       */

 

       if (typeof(conditionalFunc) != "undefined"){

          eventFunc = function(){ if (conditionalFunc()){ existingFunction()}};

       }else{

          eventFunc = existingFunction;

       }

     

      /* Add the new event handler */

      addNewEvent(formItem,eventFunc);

     

      /* Remove the old event handler */

      removeExistingEvent(formItem);

   }

}

 

The function, moveEventFunction, will move or swap the code assigned to one event handler and move it to a new event handler on the same node (or tag).  The function also gives the developer the option of wrapping a new conditional (Boolean) function around the original event handler code.

 

Now that we have a solution, how do we apply it?  You have a couple of options.  First, place the call to moveEventFunction at the bottom of the page (between script tags).  It will fire after all of the ADF/JSF  HTML has been rendered. 

 

<script>

     moveEventFunction(<id of target tag>,<existing event name>,<new event    name>,<optional conditional function>);

</script>

 

 

However, if you plan on making the target tag a partial target (dynamic refresh), you will lose the swap.  The second option handles this situation.  Place the call on the onFocus event of the target tag.  Doing so guarantees it the swap.

 

onFocus="moveEventFunction(this.id,<existing event name>,<new event name>,<optional conditional function>);"

 

The conditional function (the last parameter) can perform multiple tasks prior to executing the main function (original function).  In the case of the scenario above, the conditional function would check for the "Hot Key" that triggers our auto population. However, it must return true or false at the end of its execution.  The conditional function needs to be defined in the manner:

 

   var fnc_MyConditionalFunction = function MyConditionalFunction(){ ...}

 

This will allows allows you to pass the actual function as a parameter without it actually being executed (or evaluated) . Instead of passing in MyConditionalFunction, you pass in fnc_MyConditionalFunction.

 

(Another option that isn't JavaScript related might be to get an instance of the UIComponent prior to page rendering and make the swap ... haven't tried that yet.)

 


10:22:48 AM    

Click here to visit the Radio UserLand website. © Copyright 2008Jason Bennett.
Last update: 8/28/2008; 9:45:45 PM.

March 2008
Sun Mon Tue Wed Thu Fri Sat
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Jan   Apr