Wednesday, May 29, 2013

Passing a SSJS Function as a Custom Property to the Bootstrap Modal Dialog Custom Control

In my post on using my Bootstrap Modal Dialog Custom Control, I mentioned that I had yet to figure out how to pass code to the buttons for processing each step in the wizard.   This post explains how to process the contents of each step of your wizard.

With the help of Stack Overflow I was able to figure out how to pass a method name and execute the method in a button of the custom control.   This question/answer explains it well.  Thanks to Per Henrik Lausten for his clear and concise answer, and practical examples.

I am going to explain how I used this did this, in a way that would be helpful to anyone who implements the Bootstrap Modal Dialog Custom Control.  The steps are nearly the same for passing a SSJS function to any custom control.

1)  The first step is to create a SSJS script library to contain all the scripts for the buttons in your modal window.  (Next, Previous, Cancel)

2)  Include this script library as a resource on every calling xpage for each step.  This is the xpage that is never shown to the user.

3)  Create a new custom property for the modalWindow custom control.   Make the Type equal to "javax.faces.el.MethodBinding" and Editor as "Method Binding Editor".


4)  In each calling xpage, pass a value for the "processNextFunction" parameter.  Notice that how the parameter is passed as javascript.   Do not put open and close parentheses on the function name.

5)  In the modalWindow custom control, in the onClick event for the 'Next' button.   Have one line of code to call the function that you passed in (The middle line).

Tuesday, May 28, 2013

Learning PHP, My Observations and Comparisons to Notes & Domino

I decided a while back, that not only am I going to study topics that I need for my job, that I am going to study the alternatives to what I do.  This past long holiday weekend, I decided that first up, I was going to learn PHP.   I spend a good part of my Memorial day weekend, completing a 5 hour course on Lynda.com, as well as selected chapters of another older PHP course.   I also spend time researching the present state of PHP, and the community behind it.

PHP has been around since the late 90's and rose to prominence around 2000.  It is mature and widely adopted and is used on up to 70% of the web.   Here are my observations in no particular order.
  • It is a server-side language like SSJS or Lotusscript
  • PHP is the "successor" to CGI/Perl scripts
  • It has syntax similar to C and Java, with the use of curly braces, and semi-colons at the end of each line.   
  • You mix the code in with your HTML, like JSP and ASP.  It is analogous to using inline javascript using <script> in your HTML instead of having all your code in external files.     (You can include your code and keep it elsewhere, which I would think would be the best practice.)
  • It is like javascript in that it is a scripting language, made for a certain purpose.  It is like JS in that you can use a function, before actually writing it in the same page.   
  • It has some really weird syntax.   Instead of a dot operator it uses a " =>", and uses a "." for string concatenation.   There are also times where you actually need to leave off the closing tag.
  • It is used mainly with Apache servers as a plug in, although it also runs on IIS.   PHP will never be used in conjunction with xpages unless IBM adds it to Domino server and doing so wouldn't make a bit of sense.
  • There are loads of built-in functions to learn and use, and you can also make your own.
  • Documentation seems to be excellent.
  • Debugging looks like it is a major downside of PHP.   Without good standards, it can convoluted and become a maintenance nightmare.   Error messages are crptic (some even contain the Hebrew language).
  • PHP uses the confusing term "variable variable" which is I think is the iterator in an array of variables. There is even a special character '%' to signify a variable variable.  After learning this, I thought that they made it harder and more confusing than it needed to be.
  • There doesn't seem to be any console for debugging.  You can debug by writing variable values as HTML, and reloading page to see the value. You then remove your debug code when you get it right.
  • There are many frameworks that are built on top of PHP, the most popular being CakePHP.
  • Wordpress is built on top of PHP
  • There are Object Oriented like parts of PHP, in a similar way that there are OO like parts of Lotusscript, but it is not considered an object-oriented language.
  • PHP is usually tied together with a MySQL backend database
  • The many built in functions are like @Functions in Formula language    Think of it as combining LotusScript and @Functions together in one language.
  • You wouldn't use PHP to do anything outside of a webpage.  That is not a limitation, the language is intended that way.
  • If I was a PHP developer, I would definitely learn another language like Java or C# as a back up.  
  • In some circles, PHP is not considered a real language.  I don't know enough to form that opinion myself, but on the surface it seems untrue.   I will say this, that I think it would take the same effort for a PHP developer to learn Java as it would take for a LotusScript only developer to do the same.  
  • PHP is in decline, but will still be used for decades.  
  • PHP has a strong community that seems to have begun "circling the wagons' in it's defense.  The proponents seem a bit defensive to me, of course as a Lotus guy I understand that.
  • There seems to be quite the rivalry between Ruby and PHP, those that know both prefer Ruby
  • Since PHP is free, I don't think the PHP community has too much to worry about.   Good enough free, usually beats better paid in the eyes of most companies.
  • The general trend in web development, is for more processing to move to the client-side using javascript and ajax and away from server-side processing like PHP.   I believe that you can use PHP with ajax together.although the course I took didn't cover that.
  • It is fairly easy to begin writing PHP, and write code quickly.  Despite its quirks, it looks like a fun language to work with and to learn! 
  • Xpages > PHP.  A more fair comparison would probably be xpages compared to a PHP framework, but I do not have the knowledge yet to make that comparison. 
Those are my high level observations of PHP from a Domino/Xpages Developers perspective.   I might spend some time learning about PHP frameworks from here.  Also in the future, I intend to devote extended time to learning Node.js, Ruby on Rails, Wordpress, ASP.net, and especially Sharepoint 2013.

Thursday, May 23, 2013

Using Bootstrap Modal Dialog Control to Create a Step by Step Wizard

For my latest project, I finally got the framework complete so I can begin creating content.    As opposed to the demo in the last post, I decided to have a step-by-step wizard for data entry.   The last post showed how you could have multiple buttons on the same page.  I will probably need that technique for editing existing documents later.

I also discovered today that the extension library dialog control <xe:dialog> can be modified to act as a bootstrap modal dialog.   See this link on the new site http://bootstrap4xpages.com  by Mark Leusink for more details.   I really wish I saw this post earlier, but since I already built what I did, I am going to stay with it.

The way this works is that the calling xpage (New_PO) has a button which the user presses to begin the first step in the process.   The button starts by launching an xpage that holds the modalWindow custom control.   The control is automatically launched so that it appears to the user that it opens automatically.  In actuality, I have an unnamed button that is launched using jQuery upon page load. This works really well.   Here is the very simple code:

 $(document).ready(function(){
$('a.btn').trigger('click');
});

Note that there is one of these 'shell' xpages for each step in the wizard.  They are needed because you can't link to a custom control, that really doesn't make sense.   There is one shell xpage per step and they are all the exact same code with the exception of the custom properties.

Since the last few posts, I have needed to make several modifications to fit my current project.  These are the changes I made to the modalWindow custom control.

  1. Removed slide effect from the modal window.   The effect, although cool, was a bit of an eye strain, and more importantly caused vertical centering issues on a mobile user agent.    I changed it the button class from class="modal fade hide" to class="modal hide".
  2. Prevented the user from closing the dialog by using the escape key.  This is done by adding data-keyboard="false" to the button or anchor that launches the modal window.
  3. Likewise, I needed to prevent the window from closing when they click off the window.  This is done by adding data-backdrop="static" to the button or anchor.   
  4. Added new custom control property definitions for the nextXPage, and the cancelXPage.   The nextXPage controls which xpage is opened next, and the cancelXPage property takes it back to the beginning xpage.  Without it, the user would be taken to the xpage containing the launch button that they are not intended to ever see.   I will need to add a SSJS function to these as well going forward to process the contents of each window. UPDATE:  I figured out how to add SSJS functions to process the contents of each window, see this post.
I think this solution will be fairly portable, and it is not as complicated as it seems.   Here is a drawing to illustrate.   The blue area is where I begin to develop application specific input fields.  The blue area is where the application specific code will go, the rest will work for any app using this technique (with the exception of the six custom properties).  

Monday, May 20, 2013

Bootstrap Modal Dialog Custom Control

In this post I will show the Custom Control that I created to handle Bootstrap modal dialogs.   At this point, I am not sure if I am going to use it exactly as shown but I wanted to document it in case I needed it later and also to share in case it is helpful to someone else.   This code is originally based on this example from the Bootstrap site.



  • This control can be added multiple times to an xpage for different dialogs.   
  • Key elements of the window are passed to the custom control as parameters
  • The main content of the control is passed as custom control.   I use the <xp:include> control to accept the name of the passed control.
  • I use jQuery to trick the control to using the correct id that I want to open
  • I had to remove data-dismiss="modal" from the example to get the windows to close properly. I have no idea why this worked except that it did.
Here is a screenshot of the xpage that calls the modal windows

Here is the code for the calling buttons.  You can see that four parameters are passed to the "modalWindow" custom control.   The  third parameter "mainContent" is the name of the custom control that holds the contents of the window.   The "id_name" parameter determines which window on the page to open.  In the code below, you will see how I replace the "id" with the "id_name" that is passed.

<a href="#step1" role="button" class="btn" data-toggle="modal">
Modal Window #1</a>
<xc:modalWindow button_title="Save and Continue to Step 1"
window_title="Create New PO - Step 1 of 7" mainContent="NewPO_Step1"
id_name="step1" />
<br />
<a href="#step2" role="button" class="btn" data-toggle="modal">
Modal Window #2</a>
<xc:modalWindow button_title="Save and Continue to Step 2"
window_title="Create New PO - Step 2 of 7" mainContent="NewPO_Step2"
id_name="step2" />

The result of pushing the first button
The result of pushing the second button
Here is the code for the modalWindow custom control. Note that this is a work in progress. I will try to make sense of this by footnoting parts that might be confusing.

<?xml version="1.0" encoding="UTF-8"?> <xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex" xmlns:xc="http://www.ibm.com/xsp/custom"> <xp:text escape="true" id="computedField1"> 1)<xp:this.value><![CDATA[#{javascript:var idName = compositeData.id_name view.postScript("$('#default').attr('id', '" + idName + "');") }]]></xp:this.value></xp:text>
2)<div id="default" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-header"> <button type="button" class="close" aria-hidden="true"> × </button> <h3 id="myModalLabel"> 3)<xp:text escape="true" id="computedField3" value="#{javascript:compositeData.window_title}" /></h3> </div> <div class="modal-body"> 4)<xp:include id="include1">
<xp:this.pageName><![CDATA[${javascript:compositeData.mainContent + ".xsp"}]]></xp:this.pageName> </xp:include> </div> <div class="modal-footer"> <button class="btn" aria-hidden="true"> Cancel </button> 5)<xp:button value="#{javascript:compositeData.button_title}" id="button1" loaded="true"> <xp:this.attrs> <xp:attr name="class" value="btn btn-primary" /> </xp:this.attrs> <xp:eventHandler event="onclick" submit="true" refreshMode="complete"> <xp:this.action /> </xp:eventHandler> </xp:button> </div> </div> </xp:view>

1) This uses clientside javascript using JQuery to change the id from "default" to whatever was passed to the control in the button.
2) Two things here: The id is set to "default", which is changed at runtime. This is also one of two places where data-dismiss="modal" was removed to fix the window from not closing properly. The other place is the cancel button.
3) Reading the passed parameter to set the window title
4) Reading the passed parameter to know what custom control to call for the main content. Thanks to Knut Herrmann for helping me out on Stack Overflow to get this working.
5) Reading the passed parameter for the button title. This button was changed from an html button to an xpage button so I can write code for what to do upon submit.

Thursday, May 9, 2013

Compare with Local History in Eclipse

This post is dedicated to something I wished I learn a bit earlier in my xpages development.   There is a built-in feature of Eclipse called Compare With > Local History.   I have never even knew about this feature until I was researching the issue in the last post where I couldn't open any xpages.  Someone suggested that you use this feature to fix that problem.  While it didn't help me with that issue, I was glad that it was now on my radar.  Today, I need it since I messed up the control I was working on.


To use this, simply right click and choose Compare With, then choose Local History.  Eclipse will open the Local History window, and you can choose the version to compare by revision time.   There is also an option to Replace With > Local History.


The Text Compare window shows the two versions side by side and points out the differences.   It is really cool how Eclipse visually compares them for you.  Also notice, on the right, you can see the Local History window.  If the history I picked doesn't help I can choose another time until I find the right one.

BTW:  I am going on vacation tomorrow, so I won't be posting again for a while!

Tuesday, May 7, 2013

Could not open the editor - Problem with Opening any Xpage or Custom Control and How to Fix it.

Yesterday, I discovered a bizarre problem that I thought I would share.   I was working on a custom control when the Domino Designer began acting up.   I closed Designer and Notes and restarted.   After doing so, I could not open any xpage or custom control and got the following message when I did.

The 'Details>>' button showed the stack trace, with the exception being "org.xml.sax.SAXParseException: Premature end of file."

At first I thought it was my 9.0 client, then I thought it was our development server.   It turned out that it was a corrupted design element causing the issue.   I found a tip online to try using the Java perspective, and sure enough there was two custom controls with the same name.   The funny thing was that I hadn't touched that particular control for several days.   It turns out, that the message was actually telling me the problem control all along.   I chose to delete both copies of the control, and I was then able to continue working.

Here is what the controls looked like in the Java perspective.  I don't know why there is a UNID next to the name, but none of the others have that.  Perhaps it is because of the duplicate name.   The fourth one is likely the problem, but I deleted them all since I didn't need them.  I suspect that if the corrupted control was one that I needed then I would be out of luck.


Monday, May 6, 2013

Using Bootstap to Create a Responsive Application Design - Part 2

In Part 2, I want to share the code that I used to create the navigation for my application.   The technique I am using with Bootstrap, is very analogous to using the extlib Application Layout Control.   You create your layout once in a custom control, and then add it to each xpage in your application.   You then add content in the facet area of your layout.  

Presently, my layout is basically done, and I have shifted to creating the content of the application.   The application is fairly straightforward, so I was able to put the whole layout in two custom controls.   The screen shots in the previous post will show you what this looks like.

The layout custom control shown here, contains the Bootstrap grid, and calls the header custom control.  I am using a grid of 1-10-1.


<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom">

<!-- Fix for IE8 -->
<xp:text escape="false" id="computedField1"
rendered="#{javascript:context.getUserAgent().isIE(0,8)}">
<xp:this.value><![CDATA[#{javascript:"<style type='text/css'>body {padding-top: 45px; padding-bottom: 40px; }</style>"}]]></xp:this.value>
</xp:text>

<div class="container-fluid">
<xc:header showCategories="true" />
<div class="row-fluid">
<div class="span1 visible-desktop">
<xp:callback facetName="leftColumn" disableTheme="true" />
</div>
<div id="mainContent" class="span10">
<xp:callback disableTheme="true" />
</div>
<div id="rightColumn" class="span1 hidden-phone">
<xp:callback facetName="rightColumn" disableTheme="true" />
</div>
</div>
</div>
</xp:view>

The header custom control is more complicated and contains different menu listings for a desktop and mobile device.   This CC contains all the menu navigation.  

 Here is a key to what each section does.  See the corresponding code in red.

  1. Uses Google Web font
  2. Creates Bootstrap Navbar fixed to the top
  3. Creates Mobile menu button that only shows when collapsed
  4. Creates the "Brand" which is the company name, I show different brands for different devices
  5. Creates dropdown capable menu
  6. Creates listing with dropdown values
  7. Create a caret to indicate dropdown choices
  8. Creates different listing of menu items for mobile devices, this way I can limit choices a mobile sees if I choose.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom">

1.)<link href='http://fonts.googleapis.com/css?family=Oxygen' rel='stylesheet'
type='text/css' />
2)<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
3)<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar" />
<span class="icon-bar" />
<span class="icon-bar" />
</a>
4)<a class="brand" href="/po/po.nsf">
<span class="hidden-phone float-left">
<xp:image url="/harmons_reverse.png" id="image1" />
<span id="brand-label-big">
<xp:label value="&#160;&#160;Purchase Orders" id="label1" />
</span>
</span>
<span class="visible-phone" id="phone-text">
<xp:image url="/harmons_reverse_phone.png" id="image2" />
&#160;&#160;Purchase Orders
</span>
</a>
5)<div class="visible-desktop dropdown">
<ul class="nav nav-pills">
<li class="${javascript:view.pageName == '/follow.xsp' ? 'active' : ''}">
6)<a class="dropdown-toggle" data-toggle="dropdown" href="#">
View PO's
7)<b class="caret" /></a>

<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<xp:link text="Active PO's"  value="/Active_PO.xsp" />
<xp:link text="Pending PO's" 
value="/Pending_PO.xsp" />
<xp:link text="Completed PO's" 
value="/Completed_PO.xsp" />
<li class="divider" />
<xp:link text="All PO's" value="/All_PO.xsp" />
</ul>
</li>
<li class="${javascript:view.pageName == '/about.xsp' ? 'active' : ''}">
<xp:link text="Manage Vendor Info" />
</li>
<li
class="${javascript:view.pageName == '/contact.xsp' ? 'active' : ''}">
<xp:link text="Create New PO" 
value="/New_PO.xsp" />
</li>
</ul>

8)<div class="collapse nav-collapse hidden-desktop dropdown">
<ul class="nav nav-list">
<li>
<xp:link text="Create New PO" 
value="/New_PO.xsp" />
</li>
<li>
<xp:link text="Active PO's" value="/Active_PO.xsp" />
</li>
<li>
<xp:link text="Pending PO's"  value="/Pending_PO.xsp" />
</li>
<li>
<xp:link text="Completed PO's" 
value="/Completed_PO.xsp" />
</li>
<li>
<xp:link text="All PO's" value="/All_PO.xsp" />
</li>
<li>
<xp:link text="Manage Vendor Info" />
</li>
</ul>
</div>
</div>
</div>
</div>
</xp:view>