Wednesday, October 05, 2011

Changing the Search Page Operator

I just posted about Monkey Patching, a technique used in chapter 7 of my book PeopleTools Tips and Techniques to set the default search page operator on advanced search pages (Note: only 8.50 and later required Monkey Patching). As I was looking over the "Changing Search Operators" section of chapter 7, I noticed the code was missing a few lines (pages 293 - 296). Here is my revision:

<script type="text/javascript">
  // C style include protection
  if(!window.apt.setSearchOp) {
    window.apt.setSearchOp = true;
    
    if(window.net) {
      // pt 8.50
      (function($) {
        var originalContentLoader = net.ContentLoader;
        net.ContentLoader = function(url,form,name,method,onload,onerror,params,contentType,bAjax,bPrompt) {
          var originalOnLoad = onload;
          if(name == "#ICAdvSearch") {
            onload = function() {
              if (typeof originalOnLoad == "undefined" || !originalOnLoad) {
                this.processXML();
              } else {
                originalOnLoad.call(this);
              }
      
              // The value for "between" is 9. Change this to your desired
              // search operator value.
              var newValue = 9;

              // The name of the search key field is APT_UI_SCRIPTS_MENUNAME.
              // Generally speaking, PeopleSoft creates HTML element names by
              // combining record and field names with an underscore as in
              // RECORD_FIELD. Change the following value to the name of your
              // search key record_field
              var coll = $("select[name='APT_UI_SCRIPTS_MENUNAME$op']");
              if(coll.val() != newValue) {
                coll.val(newValue).change();
              }
            }
          }
          return new originalContentLoader (url,form,name,method,onload,onerror,params,contentType,bAjax,bPrompt);
        }
      })(window.jQuery);
    } else {
      // pt 8.4x, $(document).ready below will handle pt 8.4x
    }
  
    // just in case advanced is the initial view
    $(document).ready(function() {
      var newValue = 9;
      var coll = $("select[name='APT_UI_SCRIPTS_MENUNAME$op']");
      if(coll.val() != newValue) {
        coll.val(newValue).change();
      }
    });
  }
</script>

9 comments:

Paul said...

Hi Jim, thanks for so much spectacular content! I wonder if you have a suggestion for approaching this requirement. I'd like to make PeopleSoft search pages default to the stylesheet of the first page in the component they are hanging from - of course in the least-invasive way possible.

Thanks in advance for any help you can give.

Jim Marion said...

@Paul, that is a great use case. As you know, there is no design mode for search pages, so it is not possible to modify them directly. You can, however, modify them from JavaScript. The trick will be executing the JavaScript so that it imports your CSS before the page is fully displayed. Otherwise your page might look a little funny.

In my book I show how to add JavaScript to PT_COPYURL. I used PT_COPYURL in my book because PT 8.49 had a size limit. As of 8.50, that is no longer the case, so you can now use PT_PAGESCRIPT, etc. Once you pick a JavaScript HTML definition, add some JavaScript to make an Ajax call to an iScript. That iScript will read the database to determine the page's stylesheet and will write back %Response.GetStylesheetURL. You will want your Ajax to be synchronous (blocking) and you will want to use document.write to create the stylesheet link in your search page.

Making a blocking ajax call on load will have an impact on performance. If you don't mind the screen flicker of loading up a new stylesheet after the page is loaded, then you can go with non blocking and import the stylesheet using the technique mentioned in my Importing Custom Stylesheets post.

In my book, I show how to add approximately 10 lines of JavaScript to PT_COPYURL, and that 10 lines imports jQuery and then runs an iScript to determine additional content to add to the page (search pages included). It is non-blocking, so CSS imports may look a little funny.

Paul said...

Thanks for the detailed response, Jim! We will buy your book and try it out, and let you know how it goes.

Jim Marion said...

@Paul, Sorry, I didn't mean to push the book so hard in my response. I just assumed everyone already had it ;). And, I wanted to get you an answer rather than have you wait for me to write up a full response.

The book is available through Safari Books Online, and several other online media, so if you already have a subscription somewhere, then you should have access.

Paul said...

@Jim Oh, no problem there at all - I've been meaning to buy it anyway, and if it saves me an hour of work on this issue I'll have already paid for it. You provided plenty of free advice in your reply - knowing the destination I need to reach, I'm happy to buy the ticket!-)

Leandro said...

Jim, after implementing a slightly different version of the "configurable user interface" functionality described in chapter 7 of your book, I noticed in the browser's JavaScript console that I keep getting the following warning (always twice in a row):

Warning: A call to document.write() from an asynchronously-loaded external script was ignored.
Source File: [URL of currently-displayed PeopleSoft content]
Line: 0

Despite this warning, everything seems to work relatively well. Any idea how I can debug this?

Jim Marion said...

@Leandro, that may be caused by a difference between PT 8.49 and 8.50+. 8.49 performed full page refreshes when loading pages. 8.50+ systems use Ajax. document.write called after $(document).ready will overwrite the entire page. That is why you receive the warning. I will make note of this for the next version of the book.

In the code, you will notice that the import script function uses document.write until a certain point, and then changes the definition of the import script function to one that creates a script node. Given 8.50+'s Ajax design, document.write should no longer be the default. Instead, it should be replaced with a check to see if the page is loaded. If it is, then use the script node variety. Otherwise, use document.write.

I am surprised it is working with document.write.

jb said...

Jim, can this be done in a PeopleCode event just before I call a DoModalComponent function?

I want to change the operator to 'in' so I can pass a list of possible values to search for.

Joe B.

Jim Marion said...

@jb, no, unfortunately, it is not possible to change the search page operator using PeopleCode. You can only do this through JavaScript.