Wednesday, June 26, 2013

Using PeopleCode Modals: openPageletActionPageInModal (PeopleTools 8.53)

While typing something in the Chrome JavaScript console, I managed to bring up the function openPageletActionPageInModal. Hmmm, sounds interesting. I drilled to the implementation and saw that you call it like this:

openPageletActionPageInModal("http://your.server.name/psp/ps/EMPLOYEE/HRMS/c/ROLE_EMPLOYEE.HR_EE_PERS_INFO.GBL?")

What does it do? It converts the /psp/ part of the URL to /psc/ and opens the URL in a modal dialog. For me it worked great as long as I followed two simple rules:

  • Included a question mark in the URL. If the URL has no query string parameters, just include a trailing "?".
  • Used this function in the same datababase/application as the content. In other words, I didn't try to use this technique in Interaction Hub for HRMS content. For that to work, I would need to translate more than just /psp/. I would also have to translate the server name and site name.

Note: It works just fine in a portal/content provider situation if the URL is already a /psc/ URL.

Anyway, interesting, undocumented piece of JavaScript that you may or may not find useful. As always, your mileage may vary.

Note: I was using PeopleTools 8.53 when I found this function.

Tuesday, June 25, 2013

Using the PeopleTools 8.53 Version of jQuery "Safely"

Now that PeopleTools 8.53 includes jQuery, the question is, "how do I use it?" Probably the easiest way is to add something like this to your Pagelet or page where you want to use jQuery (see New PeopleTools 8.53 Branding Tools):

<script type="text/javascript" src="/psc/ps/EMPLOYEE/EMPL/s/WEBLIB_PTBR.ISCRIPT1.FieldFormula.IScript_GET_JS?ID=PT_JQUERY_1_6_2_JS"></script>

Some of you may have tried this. It works great if you have just one item that uses jQuery. If you add more (for example, if you add multiple pagelets) where some use plain jQuery, some use jQuery UI, and others use jQuery Cycle, you will see that each new inclusion overwrites your plugin list, rendering your new pagelet unusable. What about include protection? This concept is still relevant, but I would hate to manage it as a modification if there was another way. Here is what I came up with for 8.53:

<script type="text/javascript" src="/psc/ps/EMPLOYEE/EMPL/s/WEBLIB_PTBR.ISCRIPT1.FieldFormula.IScript_GET_JS?ID=PT_JQUERY_1_6_2_JS"></script>
<script type="text/javascript">
  // special variable to store "our" single jQuery instance
  if(!window.psjq$) {
    window.psjq$ = window.$ = window.jQuery;
  } else {
    // ignore recent import and use the global single instance
    window.jQuery = window.$ = psjq$;
  }
</script>

If you look at the PT_JQUERY_1_6_2_JS HTML definition in app designer, you will see that PeopleTools uses jQuery.noConflict() to free up $, but not jQuery. Using noConflict to move $ into a new variable named ptjq162 is appropriate, but doesn't help with plugins. Properly coded plugins use the global variable window.jQuery. Looking through jQuery UI, cycle, and many of the other plugins I use, they all use the global jQuery variable, with no mechanism for replacing it. As you can see here, my solution is to store jQuery in the custom global variable psjq$, and then override jQuery on each import of jQuery. This way all plugin scripts loaded after my script will always use the original, single instance jQuery copy of psjq$. Note: I tried using ptjq162.noConflict(true) to manage a single instance, but didn't get it working. My approach just seemed easier for me to understand, and, well, it just worked.

I don't have much "burn in" time with this, so I'm open to suggestions. One key difference between this approach and the Include Protection approach is this approach processes jQuery for each jQuery include. It drops it after processing it, but you still take the performance hit (you may not notice it, but it is still there). The include Protection approach only processes jQuery once.

Note: My script above assumes $ is for jQuery. The point of jQuery's noConflict is compatibility with other libraries that use $. If you find yourself in this situation, just remove $ from the assignments above. For compatibility reasons, you should probably never use $ except in a closure, but...

Warning: PT_JQUERY_1_6_2_JS is NOT safe for use with multiple versions of jQuery. The noConflict call at the end of the script is compatible with $, so if you have another, more recent version of jQuery, $ will still point to your newer version. The jQuery variable, however, will only point to the last version parsed (or the last assignment, as shown above). $ is nice, but it is really the jQuery variable that matters. To be compatible with other versions of jQuery, the HTML definition would have to use jQuery.noConflict(true). The jQuery docs don't recommend having two versions on the same page, but it is important to note.