Sunday, February 21, 2010

Page Assembler Strips Empty Elements -- This is Good!

With the new release of PeopleTools and Enterprise Portal, I find myself modifying my old branding themes to incorporate new features. While testing a header, I noticed that it appeared correctly on homepages, but not on transaction pages. Upon further inspection, I noticed that certain HTML elements I included in my HTML definition appeared on homepages, but not on transaction pages. Specifically, if an HTML element had a bind variable as its only content and that bind variable was only relevant on a homepage, then the page assembler would strip my hard-coded empty element from the transaction page. This caused me a bit of concern because I was actually using those elements to provide layout and styling. Consider the "Personalize Content | Layout" links that usually appear underneath the tabs in a standard Enterprise Portal implementation. Those links only appear on homepages, not on transaction pages. The PeopleSoft branding/assembly code uses designated bind variables to insert those links into a header HTML definition. If you wrap a block element, such as an HTML div around that bind variable, then your div will appear on a homepage, but not on a transaction page.

When I saw this behavior the other day I was quite surprised... and then I remembered I had seen it before. Several years ago while working with page level HTML Areas and Ajax, I noticed the same behavior. It is quite common to insert empty, hidden div elements and other structural elements into HTML to act as containers for dynamic content. The only problem with this approach is that the page assembler seems to eliminate these empty elements. Here is the workaround I contrived for this issue: Add an HTML comment inside an empty HTML element as follows:

<div id="jjm_dynamicContent" style="height: 10px; background-color: blue;">
<!-- This comment will force the page assembler to render this element -->
</div>

The page assembler will see content (the comment) inside the element and will allow it to pass through to the browser. Since the content is a comment, the browser will ignore the content and treat the element as if it were empty, giving us our much desired empty element.

Now that we have a solution for creating empty elements, let's consider how to turn this seemingly annoying behavior into a positive feature. The PeopleTools branding makes extensive use of HTML definitions. These HTML definitions contain bind variables that may or may not have values, depending on the execution context. I've already given the example of the Personalize links on a homepage. Wrapping items like these in HTML containers, such as div elements, provides us with conditionals that otherwise might not exist. For example, by wrapping the Personalize bind variable in a named div, you create a div that will exist on homepages, but not on transaction pages. Using JavaScript, you can test for the existence of this named element and execute code accordingly. Likewise, you can use CSS to attach layout and design instructions to these elements that the browser will only apply if the element exists (conditions are met).

There was a time when I thought this was a bug that should be fixed. But, now that I am enlightened to the possibilities of conditionals, I see the benefits of this feature and would be very sorry to see this behavior change.

15 comments:

DuncanDavies said...

This explains a lot. I'd hit this issue before when creating pagelets with empty elements (which get populated later with dynamic content).

Jim Marion said...

Thank you Duncan for confirming your experience with this. I have never seen the internal PeopleSoft code. I'm only writing from my experiences with PeopleSoft's handling of empty HTML elements and how I work around this issue.

Unknown said...

Jim,

You should also be able to use a non-breaking space character entity as a placeholder for a div. It's actually tidy that is stripping the empty elements during the page assembly process.

Mark

Jim Marion said...

@Mark, thank you for the clarification. I thought it was Tidy, but wasn't certain :). Using &nbsp; is another good option. The difference between an HTML comment and a non breaking space is that &nbsp; adds another node to the DOM tree. If it is hidden and you plan to replace the contents anyway, it doesn't matter. If you are planning to append to the contents of the container (div), then it might matter.

Anand said...

PeopleSoftNet
Hello Jim,
Thanks for such a nice blog.
We would like to have your comments on below site being developed for peoplesoft developers to help PeopleSoft Community.
we expect response from you.
Thanks in advance for your time and comments.
We need a guidance from an expert like you.
PeopleSoftNet

Pankil said...

Hi Jim

I have found a hidden column on page order tab. Its called "Out of available memory". Its located after Allow column. It is hidden by default. I could not find any documentation on this column. Would you have any idea on what it does?

Anand said...

Pankil,
Thanks to tell how you enabled this hidden feild as I am not able to see it
PeopleSoftNet

Pankil said...

Anand

I did not enable it. It is there. You have to drag the column boundary to see it.

Unknown said...

I've seen this as well in much earlier versions of PeopleTools (5-6 years ago) however I thought it was Tidy that was stripping the empty elements. I also employed a similiar trick in using an HTML comment block within the empty tag.

Jim Marion said...

@ropatel, I believe you are correct as that is one of the steps in page assembly.

Unknown said...

Jim,

Very informative blog you have.

Got a question...I need to record the number of page hits of a particular read-only PeopleSoft page. So I am thinking of some javascript which can insert data into the database every time the activate of a page fires...any thoughts on how to go about it ?

Jim Marion said...

@Dileep, I think the easiest way to do this is to create a JavaScript that calls an iScript and passes the page, component, etc, to the iScript. The iScript will run as the user, so you will have %OperatorId, etc.

As far as injecting the script into all PeopleSoft pages, I recommend using my custom scripts module documented in chapters 6 through 8 of my PeopleTools Tips and Techniques book. Basically, you inject the iScript call from PT_COPYURL. The code in my book includes JavaScript functions/methods for parsing the menu, market, component, and page name from strCurrUrl.

Satish said...

Hello Jim,
I'm trying to call an iframe using an IScript within a peoplesoft page. But when I look at the source, I don't see my iframe tag within the html source. It looks like the page processor strips the iframe tag. Have you ever noticed that. I even tried enclosing it within div tags and it still strips it. How do I work around this limitation

-Satish

Jim Marion said...

@Satish, did you try adding a comment inside the iframe like <iframe ...><!-- temporary content --></iframe>

Satish said...

Nice! That seemed to have done the trick! I guess the idea is to force the page assembler to process the comment, which is inside the tag we wanted preserved.
As always, thanks a bunch for your help! Please keep up the good work!

-Satish