Thursday, February 10, 2011

JavaScript Meta blog

JavaScript is a critical component of PeopleSoft applications. With the web browser pretty much taking over as the rendering engine for enterprise applications, I see JavaScript as a critical language for computer professionals. Of course, technologies like PeopleTools and ADF contain abstraction layers so application developers do not have to write JavaScript, but, in the end, someone has to write the JavaScript generated by those abstraction layers. And, if something goes wrong, odds are very good you will have to dig through the generated JavaScript to see what went wrong (where, when, why, etc).

Anyway, I think JavaScript is one of the most important modern languages a programmer can learn, and I know I'm not alone in this opinion. Of late, I've found some very interesting online resources for people interested in learning JavaScript, so I wrote this post to pass those resources along to PeopleSoft developers.

I will maintain this as a "Meta-blog" post and update it as I find more resources. I will attempt to keep the list short, so you don't have to sift through thousands of irrelevant tutorials. Restated: this is not a complete list. It is just a short list of tutorials that I think stand above the rest.

29 comments:

Dan Kibler said...

Hi Jim

I'd be honored if you would include links to my JavaScript-related posts.

http://danielkibler.blogspot.com/2010/10/using-jquery-in-peoplesoft-introduction.html

http://danielkibler.blogspot.com/2010/11/using-jquery-in-peoplesoft-validating.html

http://danielkibler.blogspot.com/2010/11/using-javascript-in-peoplesoft-proxy.html

I have a new one drafted I hope to post soon.

Regards
Dan

Dan Kibler said...

I just added a new JavaScript-related post to my blog.

Using JavaScript in PeopleSoft: Creating your own dialog boxes

Dan

Manoj said...

Hi Jim,

I have been an ardent follower of your Journal/book. You have been my inspiration as far JS in PeopleSoft goes.

So i have been experimenting with JavaScript, jQuery & PeopleSoft. I thought of spicing up my PeopleSoft system by replacing static navigation options with some CSS based navigations.

But for the actual work to be done, I still used the PeopleCode. For instance, I defined my custom hyperlink as say: " %SubmitScriptName(document.%FormName,'UN_HRS_APPL_WRK_ADD_PB');".

So I can spice it up as if it was a custom link and still get the PeopleCode to fire.

But i've into problems. As soon as the PeopleCode fires, it clears all my injected JavaScript.

Say i have my script in a HTMLAREA. Before the code fires through my'%SubmitScript' the script is available in my Pagesource, but it disappears as soon as the code fires.

Do you happen to know why this would happen?

Paul said...

Hi Jim,
I've run into an interesting situation while implementing the custom UI scripts ideas in your book. It appears that the javascript gets loaded twice on delivered pages but only once on custom pages. I discovered this by trying to find a way to reliably get the page name across all (or the majority of) pages. As an example: if I add a new script (say, alert("test")) and attach it to any delivered menu/component i will get two alerts. If I attach it to a custom menu/component I only get one alert.

I noticed the help link in the pagebar uses the page name as the context id parameter. I was attempting to strip the page name from this URL. I still haven't tracked down why, yet, but the URL is populated on the first loading of the javascript but blank on the second loading of the javascript (which prevents me from using the help link to get the page name).

Have you seen this before? If so, do you know why it happens? (Also, I'd be happy to explain what we're using your fantastic utility for if you're interested.)

thanks for your time!
Paul

Jim Marion said...

@Manoj, I think I would have to see it to know what to do about it. I don't think I've attempted to do what you are trying to do.

Jim Marion said...

@Paul, that is very interesting. Whether the component is custom or delivered, it should behave the same. Do your custom components use the same CREF template? That is the only thing I can think of -- if your code is firing for both the header frame and for the TargetContent frame.

To find the menu, component, or page name, I use the strCurrUrl JavaScript variable.

Paul said...

Jim, Have you had a chance to test your javascript from the book on peopletools greater then 8.51.05? We're on 8.51.07 and it looks like oracle has locked down some of what you're allowed to do. Document.write is no longer allowed, for instance and appending scripts to the head is also working differently. They've even stopped you from inserting closing script tags in html definitions.

Jim Marion said...

@Paul, yes I have had a chance to implement some of the code on PeopleTools 8.50, and now 8.51. The key difference is $(document).ready. It doesn't work the same because PeopleTools no longer reloads the page. Instead, I use a technique called "Monkey patching" or "Duck punching." What I do is override the net.contentLoader (or something like that, can't remember) in a closure so I can do additional processing. I think my book's JavaScript for changing the search operator has some of this code in it.

citizen6in said...

@jim: we have a requirement where in we dont want the 'Add an Attachment's pop up on the main page. The pop up contains Textbox, browse, upload and cancel button. when user clicks the 'Add an Attachment' button, user shuld be shown the File browse dialog, if a file is selected then the file should be uploaded. Our customisation for tools less than 8.50 did not work in 8.50, as we have pop up. Is there a way to do this. atleast with jQuery.?

Jim Marion said...

@citizen6in, I have not tried that before. I see your point though. Why show that prompt? Why not just open the file dialog? Since I haven't looked into the JavaScript for the Add Attachment button, I can't give you much more than just a place to start. Add Attachment buttons usually execute FieldChange PeopleCode. In 8.50 this will cause an Ajax request/response. I suggest you use Fiddler/Firebug to inspect the Ajax request and response. In there you should see the JavaScript required to display that dialog. Once you discover the JavaScript behind the buttons, you can start Monkey Patching the methods/functions so that they behave the way you require.

Marc said...

I have used jQuery to manipulate grids so that the "Click column heading to sort ascending" title is changed to "Click column heading to sort ascending by fieldname". This was to help with some 508 Compliance issues with PeopleSoft.

/* Set the hover text for the column headings */
$('a.PSLEVEL1GRIDCOLUMNHDR').each(function (index) {
var hdgObj = $(this);
var hdgTitle = hdgObj.attr('title');
var hdgText = hdgObj.text();
if (hdgTitle.indexOf("by") !== -1) {
}
else
{
var newTitle = hdgTitle + " by " + hdgText;
hdgObj.attr('title', newTitle);
}
})

Anwway, I need to do the same for the search pages and I have yet to figure out where the code is for building the search results so that I can manipulate things. I have noticed that my code does not get fired when the search button is pressed, so I am assuming that I cannot use the $(document).ready(function (), since PeopleSoft is no longer reloading the page. Any suggestions that you can provide?

Regards,
Marc

Jim Marion said...

@Marc, First, use Firebug to see what scripts are loaded into the search page (PT_PAGESCRIPT, etc). These are HTML Definitions in App Designer. You can use one of them as your delivery vehicle. Second, $(document).ready doesn't fire on PT 8.50 and greater after search button click because the request/response is all Ajax (you already figured this out). In my book (chapter 7) I have an example of Monkeypatching the search page's net.ContentLoader, which is the Ajax service for PT 8.50. My example shows how execute a function after the advanced search button click returns a response. Your scenario would be very similar.

If you use something like PT_PAGESCRIPT as your delivery mechanism, then you need to have a way to determine if you are on a search page. Here is what I use:

if($("#\\#ICSearch").length > 0) {
// search page
} else {
// do nothing
}

krunal mehta said...

Hi, recently we have upgraded our PeopleTools from 8.49.23 to 8.52.09.



After this we are facing the issue like the processing image is keep on running. For ex: If I navigate to Structure and Content --> Portal Objects --> Home Page-->Tabs -->Home



In that if I am clicking any tab it will load the page but the processing image keeps running. I see an error in the status bar like below



Webpage error details



User Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)

Timestamp: Thu, 11 Oct 2012 05:19:41 UTC

Message: Permission denied

Line: 1602

Char: 5

Code: 0

URI: http://askhrtest.hk.standardchartered.com:8522/cs/DGEPUPG1/cache/PT_PAGESCRIPT_win0_291.js

Message: Permission denied

Line: 1602

Char: 5

Code: 0

URI: http://askhrtest.hk.standardchartered.com:8522/cs/DGEPUPG1/cache/PT_PAGESCRIPT_win0_291.js.



Sometimes it is showing permission denied error on PT_COMMON script.



We are not facing this issue when we do the same thing in Chrome Version 22.0.1229.79. But our organization standard browser is Internet Explorer .8.0.6001.18702



Please help us to find the issue.
Thanks for your time.

Jim Marion said...

@krunal, did you set the Auth Token Domain in your web profile?

You might get better results if you post this question in the PeopleSoft OTN Forum.

krunal mehta said...

Auth token is set up at the web server level and also at the web profile. Not sure how do we need to analyze/fix this issue. Please guide us to resolve the same

Jim Marion said...

@Krunal, the brightest PeopleSoft minds in the world monitor the OTN and ITToolbox forums. Here you will only get my assistance. Post your question in either the PeopleSoft OTN general forum or the ITToolbox PeopleTools forums and I'm sure someone that has experienced that issue will respond.

Hari said...

Dear Jim,

We have finally found the below error is not due to the permission issue

Message: Permission denied

Line: 1602

Char: 5

Code: 0

URI: http://askhrtest.hk.standardchartered.com:8522/cs/DGEPUPG1/cache/PT_PAGESCRIPT_win0_291.js

It looks like there is some problem with the Java Script execution. While loading the page JS getting error and stops further processing due to this we are getting the processing image as its waiting for the execution to complete.

When I try to debug the JS error it stops at the below line (which is given as bold text)

function doModalOnLoad_win0(bStartUp) {
mTop = MTop(); // top window
if (!mTop || typeof mTop.oParentWin == 'undefined' || !mTop.oParentWin) return;
Not sure how this Mtop() is working and what it is expecting to complete the execution? Could you please help us?

Thanks a lot for your time.



Jim Marion said...

@Hari, When your web browser throws a permission denied error, it means the JavaScript attempted to perform an operation that is considered insecure. Usually this is caused by trying to access a frame from a different domain. Make sure the top level page and your transaction page have the same "document.domain" value. You can check this from the JavaScript console in any browser. Also take each fragment of the if statement and execute it in the JavaScript console to see which part is throwing the access violation. Don't be surprised if the error is really somewhere else in the JavaScript.

Another thing you can test is adding your PeopleSoft application domain to your list of trusted sites.

Peter Nguyen said...

Jim,

Love your Blog! I'm trying to bind a JQUERY click event to a PeopleTools Button/HyperLink field (TYPE: Hyperlink, Destination: PeopleCode Command), so that when the user clicks the hyperlink a loader/spinner icon appears and makes an ajax call to an iscript,
but whenever I click the hyperlink it hits PT_PAGESCRIPT:submitAction and it strips the field element of all the attributes I set using my jquery callback function and returns it to the state it was in before I clicked it. I can get this to work using an html area or any other field for that matter, but just wondered if there was a work around for the PeopleTool button.

Jim Marion said...

@Peter, thank you for the compliments.

When creating buttons that look like PeopleSoft buttons, but behave differently, I usually use an HTML Area and copy the HTML from a PeopleSoft button into the HTML Area. I change the ID, name, and onclick handler.

If you want to change the way a delivered button behaves, you will need to reset the onclick attribute $element.prop("onclick", null). For hyperlinks, you can have your $.click event handler return false.

Pawan M said...

Hi Jim,

I have posted a query related to the browser permission denied error related to the Mtop function in oracle forums:

https://forums.oracle.com/forums/message.jspa?messageID=10905546#10905546

Could you take a look and offer some guidance?

sri anjana Vadevoo said...

%SUBMITSCRIPTNAME resets all my other javascript code.How do I prevent this.

Jim Marion said...

@Sri, can you elaborate? How are you using this MetaHTML? Where are you using it?

sri anjana Vadevoo said...

Hi,

I have grid column that needs to be sorted.This column is a HTML area and cannot use the delivered peoplesoft sorting ie(%submitscriptname(form,sortcolumn)).Hence I have written my own javascript code
-> to make the coulmn heading a link
->to sort the column ascending/descending when the link is clicked.

It works fine but once I try to sort any other peoplesoft column or click download or find or in other words when %submitscriptname is called anywhere else all my JS code is reset.My column heading is no more a link and everything is back to initial stage.Is there any way to bypass the reset?

Thanks,
Sri

Jim Marion said...

@Sri, that makes sense. When you click any link or perform any action, it submits an Ajax request. The Ajax response will overwrite the current page contents. Any JavaScript on your page will still exist, but the element bindings will not exist because the former elements will have been replaced by the Ajax response. I am not sure I like this, but it is how it works. One way I work around this is to use jQuery's live method for event binding. Another approach is to "monkey patch" net.ContentLoader so you can rebind your event handler after the Ajax response.

Kevin Weaver said...

Hey Jim,

We have had multiple issues with ePerformance and our users wanted to autosave the document if the manager click's on the back button. So I was looking into doing a simple like this:

window.onbeforeunload = function () {
// stuff do do before the window is unloaded here.

submitAction_%Formname(document.%Formname,"EP_BTN_LINK_WRK_EP_STORE_PB");
// alert('Auto Save');
}


But the save only works if the alert is fired after the submitAction function? Is there a way to autosave the page if the window is unloading from either the back button or even regular navigation within the component without the alert? And if you could tell me why this only works with the alert, that would be super as well!

Thanks!

Jim Marion said...

@Kevin, I am suspecting it has something to do with timing and the request/response. With an alert, the full request/response can happen for the save. Without it, the browser is just changing pages and killing the save request. You can probably see this in Firebug. The save request would be highlighted in red in the console, and then disappear as the new page loads.

Kevin Weaver said...

I really only want the onbeforeunload to happen if the user clicks the back button. So I attempted to change the onclick event of the hyperlinks like this...


function adaptLinks() {
var links = document.getElementsByTagName('a');
for (i = 0; i != links.length; i++) {
links[i].onclick = (function () {
var origOnClick = links[i].onclick;
return function (e) {
window.onbeforeunload = function(){ };
if (origOnClick != null && !origOnClick()) {
return false;
}
}
})();
}
}
adaptLinks();



This prevents the onbeforeunload and fires the onclick method associated with the link. I wonder if I could use jQuery or something cool like that to select all the input buttons and hyperlinks to override the onclick to blank out the onbeforeunload and call the default onclick event. Then change the onbeforeunload to ask the user if they want to navigate away from the page without saving.

Thanks for you input!

Kevin

Jim Marion said...

@Kevin, I like your approach of capturing the link click before it happens. Yes, you could use jQuery to identify and handle click events. Another alternative is to monkeypatch a method like saveWarning so it calls your save if the user chooses cancel. You will also want to monkeypatch the timeout so that it saves before timing out.