Thursday, March 20, 2008

Commenting system javascript on my web-site

I've received a few requests to view the commenting system javascript from my demo web-site.
The javascript is already there for all to see, either by downloading the page or viewing the source directly.
I would definitely recommend using Firefox and Firebug when viewing as it allows you to view attached script files as well as the page source.
The screenshot shows the Script tab in Firebug, listing the script files attached to the current page. In the background you can see the source for the active file.

Most of the javascript for my demo site in contained in a single "application" file playpen.js. The code has been compressed, but not obfuscated. This means you can load it into your favorite text editor and read the full source after you've done some formatting. As far as understanding the code I would highly encourage you to look at Ext 2.0 Samples and Ext Documentation. Like anything worthwhile you need to invest time and energy to gain understanding.

The comment form is based on one of the examples for dynamic forms.

Here is a super-brief explaination, I'm a little time challenged at the moment :)

I use an application process to insert the data into the database.

The javascript to do this is on my demo site - just download the source and then format it to see what's going on.

When inserting it into the database I have to unescape the comment so it will render later. I use dbms_xmlgen.convert(:new.app_comment,dbms_xmlgen.entity_decode) to do this. There may be a better way I haven't thought of. I also strip out some html elements such as script, object, embed etc to prevent malicious attacks.

The javascript then does a PPR to display the comment immediately.

If this doesn't make sense to you, time to do some reading and learning :)

Mark

Thursday, March 6, 2008

Implementing Ext Dates in Oracle Apex

"Anonymous" asked me for more explanation on how I implemented the Ext date-picker in Oracle Apex, as seen in my demo.

Look, I don't mind answering, but please put a name on your feedback - anonymous is just rude.

Here's the plain English explanation:

We are converting a simple html input item into a Ext date-picker, which just happens to be associated with a date field in the database.

To make it easy to identify which input items to convert we assign a class of "date-picker" to the item. The code to do the conversion is shown in my demo.

The only other thing to worry about is making sure the date format of the input item matches the database date format.

Everything else you want to know can be learnt by reading the documentation.
Here are the steps:

1. Set the database date format in Apex
Lets use a mask of DD-Mon-YYYY as there's no confusion internationally.
In Apex 3.1 do this directly in Home>Application Builder>Application 200801>Shared Components>Edit Globalization Attributes.
In earlier versions, you need to create application processes for "On Load Before Header" and "On Submit After Page Submission - Before Computations and Validations" with the following code
execute immediate 'alter session set nls_date_format=''DD-Mon-YYYY''';

2. Create the date item
In Apex create a form on a table containing dates.
Make sure the item type of the date field to display as "Text Field" and not "Date Picker".
Finally add class="date-picker" in the Form Elements Attributes.

3. Add the javascript
Include the Ext javascript files in your page template, cut and paste the javascript code from the demo into your page or page template.

If you run that it all works beautifully.
You'll notice the code allows for alternative data entry format masks e.g "dd/mm/yyyy" and partial formats e.g. "dd/mm".
Thats because the alternate formats are easier for keyboard operators.
See ExtJS documentation on date formats available.

4. Optional step
You may have noticed on my demo I use "DD-MON-YYYY", not "DD-Mon-YYYY" as shown in this blog.
To achieve this I set the database format easily enough, but then had to override the default Ext date names with the following line of javascript in my application javascript file:
Date.monthNames =["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"];

This is the Ext way on internationalizing dates, so it's not a hack.
What it does is force the javascript date format "d-M-Y" to return the month in uppercase.

Anyway hope this helps.

Mark

Wednesday, February 20, 2008

Moving the Developer toolbar with ExtJS

Received and email on my blog, asking how to move the developer toolbar into the "south" region of a typical ExtJS layout. This is one of those annoyances developers see, but the end users don't. For a screenshot see my post from last year here. The solution is very short: In your page template include a div tag with an id, this is where you want the toolbar to end up. e.g. <div id="DeveloperToolbar"></div> Add the following code into your application javascript:

Ext.app.moveDeveloperToolbar = function() {
  var dest = Ext.get('DeveloperToolbar');
  if (dest) {
      var els=Ext.select("table[summary='Developer Toolbar']",false);
      els.each(function(el){
          el.replace(dest);
      })
  }
}


Ext.onReady(function() {
    /** any other stuff you want to include */   
    Ext.app.moveDeveloperToolbar();
});

The code checks the div tag exists, and then searches for a table with a summary property of "Developer Toolbar". For each instance it finds (there is only ever one), it moves it to the destination position. ExtJS has a powerful DomQuery component, well worth learning. See the DomQuery tutorial for further examples. Mark

Thursday, February 14, 2008

ExtJS Ajax Search field

Here is a screenshot of an AJAX search field running in Apex. Putting an example up on the Oracle Apex demo site may not be possible, as I call a PL/SQL package directly. It's based on the ExtJS live search sample. We were running it with Ext version 1.1, but had issues with paging. By default it uses "start" and "limit" as parameters - both reserved words with PL/SQL. If you search the Ext forums, you'll find a solution for Ext 2.0 - just search for mark.lancaster.

Wednesday, February 13, 2008

Ext JS extension like Forms LOV

Just noticed on the ExtJS forums that someone has built an extension that behaves like an Oracle Forms LOV. Here is the post and a demo. Old forms programmers never die :)

Tuesday, February 12, 2008

Building a complete Oracle Apex page template using ExtJS

Following on from my earlier post on integrating ExtJS we will now build a complete page template.
This template will contain:
  • a "north" region containing a logo, title, navigation bar and show current user
  • a "west" region containing 2 sub-regions navigation and settings
  • a "center" region containing dynamic page content
  • a "south" region for footer elements, e.g. copyright notices, links etc.
When prototyping its often easier to build using static html pages, and then load it into Oracle Apex.

Create a sub-directory in the /ext-2.0.1/examples/ directory. I've called mine "playpen", but it really doesn't matter.

Save the following text as a html file into the directory, e.g. "apex layout.html".

<html lang="&BROWSER_LANGUAGE.">
<head>
 <title>#TITLE#</title>
 <!-- standard stylesheets -->
 <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />

 <!-- this style forces form to fit screen height -->
 <style type="text/css">
   #wwvFlowForm {width:100%; height:100%;}
 </style>

 <!-- Ext scripts -->
 <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
 <script type="text/javascript" src="../../ext-all.js"></script>

 <!-- application configuration -->
 <!-- eventually move "application" script to an external file -->
 <script type="text/javascript">
   Ext.onReady(function(){

      Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

      var myForm = new Ext.Panel({
        applyTo:'wwvFlowForm',
        layout:'border',
           items:[
               new Ext.BoxComponent({ // raw
                   region:'north',
                   el: 'north',
                   height:45
               }),
               new Ext.BoxComponent({ // raw
                   region:'south',
                   el: 'south',
                   height:32
               }),
              {
               region:'west',
               id:'west-panel',
               title:'West',
               split:true,
               width: 200,
               minSize: 175,
               maxSize: 400,
               collapsible: true,
               layout:'accordion',
               layoutConfig:{
                   animate:true
               },
               items: [{
                   contentEl: 'region_position_02',
                   title:'Navigation',
                   autoScroll:true,
                   border:false
               },{
                   contentEl: 'region_position_03',
                   title:'Settings',
                   autoScroll:true,
                   border:false
               }]
           },{
               region:'center',
               contentEl:'pageContent',
               layout:'column',
               autoScroll:true
           }]
       });

   myForm.doLayout();
   });
 </script>
</head>
<body>
<form id="wwvFlowForm">

<!-- -------------------------------------BODY SECTION start------------------------------------- -->
  <div id="north">
    <table cellpadding="0" cellspacing="0" border="0" width="100%" height="45px">
      <tr>
        <td valign="top">#LOGO#</td>
        <td align="center"><span style="{  }">Integrating ExtJS javascript library with Oracle Application Express</span></td>
        <td width="300px" align="right" border="0" style="padding-right:5px">
          <div style="height:20px">&USER.</div>
          <div id="navigation_bar">#NAVIGATION_BAR#</div>
        </td>
      </tr>
    </table>
  </div>

  <div id="west"></div>

  <div id="region_position_02">#REGION_POSITION_02#</div>
  <div id="region_position_03">#REGION_POSITION_03#</div>

  <div id="pageContent">
    <div id="region_position_01">#REGION_POSITION_01#</div>
    <div id="messages" align="center">#GLOBAL_NOTIFICATION##NOTIFICATION_MESSAGE##SUCCESS_MESSAGE#</div>
    <div id="region_box_body">#BOX_BODY#</div>
    <div id="region_position_04">#REGION_POSITION_04#</div>
    <div id="region_position_05">#REGION_POSITION_05#</div>
    <div id="region_position_06">#REGION_POSITION_06#</div>
    <div id="region_position_07">#REGION_POSITION_07#</div>
    <div id="customize">#CUSTOMIZE#</div>
    <div id="region_position_08">#REGION_POSITION_08#</div>
  </div>
<!-- -------------------------------------BODY SECTION end------------------------------------- -->

</form>

  <div id="south">Some footer content here</div>
</body>
</html>


Open it in your browser and you should see something like this:



Note the "West" panel expands and collapses and is resizable, and the navigation panel is also functional. Resize the width of the West panel, then refresh the page.

Did you notice it kept the new width?

This is all managed by a single line of code:

Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

The panels that make up the page are stateful and remember position, provided a cookie has been registered. Users typically don't even notice unless you point it out to them.

Spend a bit of time looking at the script used to build the layout, consult the ExtJS doco etc.

OK, to make this an Oracle Apex template do the following:

Do a search and replace:


<form id="wwvFlowForm"> becomes #FORM_OPEN#


</form> becomes #FORM_CLOSE#

Adjust the path of the javascript and css file links, so if you followed my previous post:
../../becomes /i/themes/ext-2.0.1/

Copy and paste the content into a page template using header, body and footer regions.
The html already contains comments identifying where to cut.

Whip up a quick page to test it out, and barring any mistakes it should work just like the static version.

Enjoy.

Tuesday, February 5, 2008

Integrating Ext javascript library into Oracle Application Express

So hopefully by now you’ve been to the website http://extjs.com and had a look at samples http://extjs.com/deploy/dev/examples and are ready to get your hands dirty.

The first step is to download the latest version from http://extjs.com/download and load it onto your http server 
(version 2.0.1 at the time of writing).
For Oracle Apex this can be either:
- Embedded PL/SQL gateway
- Oracle HTTP Server and mod_plsql.

For this article I have loading the complete set of unzipped files to a new folder in the 
apex/images/themes directory:
- http server - ORACLE_BASE/ORACLE_HOME/Apache/Apache/images/themes/ext-2.0.1/
- embedded PL/SQL gateway - /i/themes/ext-2.0.1/

Note: FTP access when using the embedded PL/SQL gateway is enabled as follows:

Open SQL*Plus and connect as SYSTEM

SQL> exec dbms_xdb.setftpport('21'); PL/SQL procedure successfully completed. SQL> alter system register; System altered.
If you have any issues do an internet search for "dbms_xdb.setftpport", there are numerous posts on the topic. Once the files are uploaded you can verify using the following urls: http://hostname:port/i/themes/ext-2.0.1/docs/index.html http://hostname:port/i/themes/ext-2.0.1/examples/index.html Using Ext with Oracle Apex The first step to using Ext with Oracle Apex is to reference the javascript libraries and CSS stylesheets in your page templates. Start Apex Builder and navigate to a page template: Home> Application Builder> Application 101> Shared Components> Templates> Edit Page Template A minimal header definition would look like this:
<html lang="&BROWSER_LANGUAGE."> <head> <title>#TITLE#</title> #HEAD# <!-- standard stylesheets --> <link rel="stylesheet" type="text/css" href="/i/themes/ext-2.0.1/resources/css/ext-all.css" /> </head> <body #ONLOAD#> <!-- Ext scripts --> <script type="text/javascript" src="/i/themes/ext-2.0.1/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="/i/themes/ext-2.0.1/ext-all.js"></script> <!-- application configuration --> <!-- add your custom scripts references here --> #FORM_OPEN#
This gives us access to the entire Ext library functionality. Depending on how much Ext functionality your web-site eventually uses you may want to consider only including a subset of the library. I’ll write more on this in a later article. If your using a standard theme that comes with Oracle Apex, you will probably want to keep existing javascripts and CSS stylesheets in your definition initially. Let’s build something The first example I want to demonstrate is resizable text areas. A demo is available at http://apex.oracle.com/pls/otn/f?p=200801:2001:0 Add the following code into your page template, or directly into a page containing one or more text areas.
<script type="text/javascript"> // convert html textareas into resizable textareas function makeResizable(){ var els=Ext.select("textarea",true); els.each(function(el){ var dwrapped = new Ext.Resizable(el, { wrap:true, pinned:true, //handles:'s', width:el.getWidth(), height:el.getHeight(), minWidth:el.getWidth(), minHeight: el.getHeight() }); }) } Ext.onReady(function() { makeResizable(); }); </script>
What this script does search the html document object model (dom) for html textarea elements. Html textarea elements are converted to an Ext resizable component, with grab handles pinned (visible). The minimum height and width are constrained to the original dimensions. Uncomment the //handles:'s' line to vertically resize only. You can read more about the api on your website if you used my instructions at http://hostname:port/i/themes/ext-2.0.1/docs/output/Ext.Resizable.html, or on the Ext website at http://extjs.com/deploy/dev/docs/index.html.