I have spent the last week creating my own extension library and adding my viewpicklist and loading masks controls to it. I had lots up help because i was lost. So here are the steps i followed to get there.

1. Download the xsp starter kit from openntf.org
2. Watch Notesin9 number 64 by Tim Tripcony

Those two steps will get you a library and how to copy an existing control into your library.

Now my custom controls had css, images, and a client side js file with them. I didnt want to have to copy those to each database to use them so i had to fins a way to include the resources. One reason i told you to download the xsp starter kit was it has some classes to handle resources.

I added a new folder to my plugin project called resources, under that i had img and styles and js folders( the starter Kit already has this folder). Inside those i put my resources i needed for my custom controls. I then opened the java files for those custom controls and looked for where the resources were called. i updated the resource path like this

this is what was there

ScriptResource resources = new ScriptResource();
resources.setComponent(root);
resources.setClientSide(true);
resources.setSrc(“CustomControlLib.js”);

this is what i changed it to

ScriptResource resources = new ScriptResource();
resources.setComponent(root);
resources.setClientSide(true);
resources.setSrc(ResourceProvider.RESOURCE_PATH
+ “js/CustomControlLib.js”);

images i did like this
String iconExpr = ResourceProvider.RESOURCE_PATH + “/img/”
+ “#{javascript:compositeData.picklistButtonImg}”;

ResourceProvider is a class in the starter library that gives you your path to the the library and your files inside it. So all img links and hrefs need to updated to point to this location.

Since i did not start with the starter library, i didnt have the extension points in my plugin.xml to allow resources to be served. I got a error stating that it could not load an unregistered resource. Declan Lynch helped me figure out how to get those in there. Nathan T. Freeman helped me get my library working from a blank slate and installed. So unless you are well versed in eclipse and OSGI plugins use the starter library and take out the classes you dont want or need, then refactor it to whatever name you want.

 

These are comments i left on another blog, thought i would just make it a post

We are moving off notes, we are going to use sharepoint for files and portal, exchange for email, linc for im, and XWork server for apps.

All of our apps are Xpages, so XWork servers make allot of sense.

Outlook has plugins for Sharepoint, our ERP system, Autocad Vault, salesforce, among others, Notes does not.

Having been a Notes Dev and admin for 12 years, i think i know whats its capable of. Xpages only work offline in the client, and XPINC is buggy and very slow. Something that might surprise you is there is an offline client for sharepoint.

The saving grace of the platform, which it has always been, is the dev environment. XPages are awesome, i love them, and they dont require you to have a client, or the same email platform. The apps written in them dont say Lotus, so there is not a perception issue there. XWork server allows unlimited users and is fairly inexpensive. That will be our dev platform for complex apps.

The main problem with Lotus Notes and Users is a perception issue (‘its old and no one uses it anymore’). I am tired of fighting something that it seems IBM doesn’t care to fight for themselves. The users want outlook, here you go, i still have my dev platform and i dont have to listen to how notes sucks.

I have been down about this for a while, but look forward to new challenges and learning opportunities.

 

You can find most of this documentation around the net, the only reason i repost it is to hopefully help some with the iPad landscape loading screen.

first the code

<!-- iPhone SPLASHSCREEN-->
<link href="iphoneLowRes.png" media="(device-width: 320px)" rel="apple-touch-startup-image"/>
<!-- iPhone (Retina) SPLASHSCREEN-->
<link href="iphoneRetina.png" media="(device-width: 320px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image"/>
<!-- iPad (landscape) SPLASHSCREEN-->
<link href="ipadLandscape.png" media="(device-width: 768px) and (orientation: landscape)" rel="apple-touch-startup-image"/>
<!-- iPad (portrait) SPLASHSCREEN-->
<link href="ipadPortrait.png" media="(device-width:: 768px) and (orientation: portrait)" rel="apple-touch-startup-image"/>

Once this is added you will need to add the images to your project. Here are some sample images to show you the aspect ratio of the image and the correct size for them. I tested this on the iPhone, iPhone Retina, iPad, and iPad Retina. The tricky part was the iPad landscape image is really a portrait image of a different size than the iPad portrait image and the text and logos turned 90 degrees( look at the sample images to see what i am talking about).

Download Sample images

The images for the regulaur iPad looked good enough for a splash screen on the retina iPad, but here is the code for it if you want it, no images supplied for this.

For iPad launch images, do not include the status bar region. Create launch images of these sizes:

For portrait:
1536 x 2008 pixels (high resolution)
For landscape:
2048 x 1496 pixels (high resolution)

<link rel="apple-touch-startup-image" href="img/ipad-landscape-retina.png" media="(device-width: 768px) and (orientation:landscape) and (-webkit-min-device-pixel-ratio: 2)" /> 
<link rel="apple-touch-startup-image" href="img/ipad-portrait-retina.png" media="(device-width: 768px) and (orientation:portrait) and (-webkit-min-device-pixel-ratio: 2)" /> 

For the web clip icon sizing go to Chris Tooheys website here

http://www.dominoguru.com/pages/ibm_xpages_headtag_webclip_icons_sizing_iOS.html

 

Some of you may have noticed that if you use the onKeyUp event on an xpage and do a partial refresh of a view or repeat, if you type at a quick pace it stops updating after about two characters, thus giving you an incorrect filter.

At first i thought this was an Xpages issue, but after some google searches noticed it was an ajax issue. I found some code and modified it it to work in the viewpicklist custom control that i wrote.  Here is what i am now using for the view picklist control.

First i added an output script to the control. This delays the refresh until a user has stopped typing for 1/2 second.

 

<xp:scriptBlock id="scriptBlock1">
		<xp:this.value><![CDATA[${javascript:"var count = 0; function doMyRefresh()" +
"{   count = count+1;   setTimeout('doMyRefreshGo('+count+')',500);}; " +


"function doMyRefreshGo(currCount)" +
"{ if(currCount == count){ count = 0;" +

'XSP.partialRefreshPost("#{id:' +compositeData.dialogID + "table"+ '}", {' +
 '   onComplete: function() {'+
  '  }' +
'});' +

  
'}}'}]]></xp:this.value>
	</xp:scriptBlock>

 

 

Then i changed the onKeyUp event to call doMyRefresh() in csjs, with no update or any SSJS.

Now to do this where you dont have to compute the refresh id like in the viewpicklist custom control, its a little easier.

<xp:scriptBlock id="scriptBlock2">
		<xp:this.value><![CDATA[var count = 0; function doMyRefresh()
{count = count+1;   setTimeout('doMyRefreshGo('+count+')',500);};

function doMyRefreshGo(currCount)
{if(currCount == count){ count = 0;
XSP.partialRefreshPost('#{id:yourid}', {
onComplete: function() {
}
});
}};]]></xp:this.value>
	</xp:scriptBlock>
 

Here is the scenario…

You have a text edit box, and when you leave that field (onBur) you fire a partial refresh to update some other values on the page.  Now since it is refreshed the focus of the cursor may not be where the user clicked on the form, worse – what if the user clicked a cancel button or another button?  The user will have to click it twice, once for the partial refresh and then once to fire the button.

With a little help from Paul Withers i think i have found a good solution to this issue.

First on the Xpage in the onClientLoad() event lets declare our 2 variables

var cancelRefresh = "";
var focusOnMe = "";

Next we go to the field with the onBlur() event that fires the partial update.

Click on the onBlur() event, then click on the client tab.  In the script area enter this code where yourfieldid is the id of the field you are editing.

if(dojo.byId("#{id:yourfieldid}").value ==""){return false};
if(cancelRefresh =="Yes"){
cancelRefresh ="";
return false;
}

Next we are going to go to the outline.  In the Outline you can expand the field and see event handlers.  Click on the event handlers, then the properties tab to the right.

Then scroll down until you see the onComplete property.  Click on it and enter this code.

if(focusOnMe != ""){
dojo.byId(focusOnMe).focus();
focusOnMe =""
}

This will focus on the field we just clicked on.

The next step is to go to a button, like a cancel button, or to a field.  Click on the onMouseDown event and enter this code on the Client tab.

For a button, tell it not to update

cancelRefresh ="Yes"

For a field, tell it where to focus, where yourfieldid is the id of the field

focusOnMe = "#{id:yourfieldid}"

That should get you immediate actions on your buttons and focus on the fields you click on after the refresh has occurred.

 

This application allows you to view, edit, and create your Lotus Notes Tasks while offline on your iPhone and Android  device.  No mail or system templates need to be modified. Just install this on any 8.5.2 or above server in your environment and “Get Things Done”. The user mail files can be kept untouched on their original mail server. No upgrades needed!!

 

 

Download here Project Link

 

 

 

 

I have just released mAddressBook to OpenNTF for the new development competition.  You can sync any addressbook on your server to your phone with this application.  It works offline on iPhones and iPads and should work offline with Android as well.  There are two themes included, please let me know any comments you might have, thanks

 Download

 

Another trick to get your Xpage to load faster

On October 20, 2011, in Uncategorized, by Mark Hughes

I HATE  twisties on views on the web!!  I like to use combo-box’s at the top to filter the results.

Recently i ran into an issue getting the values for the combo-box’s.  You see, I used to just do a @DbCloumn to get the values then throw a @Unique() around that  to get my list.  And that seemed to work ok for small views, BUT in this application it had 100k documents and was taking 10-14 seconds to load the page.  I then rethought how I would get values from now on.

The first thing I did was create a new view with one column, the value i needed, and categorized it.  Next I changed the code in the computed values in the combobox to create an array, and use a ViewNavigator to get the values.

//get all end dates and then sort them

var arraydate = new Array()
var view1 = database.getView('enddates')

var nav:NotesViewNavigator = view1.createViewNav();
var entry:NotesViewEntry = nav.getFirst();
while (entry != null) {
	if (entry.isCategory()) {
		arraydate.push(entry.getColumnValues().firstElement().toString())
	}
	var tmpentry:NotesViewEntry = nav.getNextCategory();
	entry.recycle();
	entry = tmpentry;
}

//sort function for dates found on web somewhere
var dateRE = /^(\d{2})[\/\- ](\d{2})[\/\- ](\d{4})/;
function mdyOrdA(a, b){
a = a.replace(dateRE,"$3$1$2");
b = b.replace(dateRE,"$3$1$2");
if (a&gt;b) return 1;
if (a &lt;b) return -1;
return 0; }

arraydate.sort(mdyOrdA)

 

Notice the use of getNextCategory(), at fist i was using getNextEntry(date1), and that cut the load time in half, using getNextCategory() made it seem to load almost instantaneously.

Now if these values wouldn’t change very often(but they do), i would load this into an applicationScope and let the app check for its existence and only build it when the applicationScope expired.


 

 

 

My favorite 8.5.3 feature has a small flaw

On October 4, 2011, in Uncategorized, by Mark Hughes

Great news this seems to have been fixed in the Gold code!!  My errors were with 8.5.3 cd5

 

First This is one of my favorite features in 8.5.3, but there is on caveat i have found just this past weekend.

When “Use Runtime Optimized CSS an JS Resources”  is checked on the XPage tab on application properties,

and you have a css file that refferences an image like

background-image:url(‘./test.png’)

 

It will NOT display the image.

For some reason the browser thinks the image is a css file, and not an image.  It even puts it in a css named folder.  To get around this include those styles on the page instead of in a css file.  I will submit this to IBM to see if we can get it fixed.

 

Xpage ViewPicklist CC reaches 1000 Downloads

On September 8, 2011, in domino, lotus, xpages, by Mark Hughes

Thanks to all who have downloaded this custom control, i hope you enjoy using it as much as i do. I submitted this control to enter the Openntf custom control contest, though i didn’t win, i am glad it has helped so many people.

Please let me know if there are features that you would like to be added, or ideas about what could be changed.  Yes Dwain, i have seen your suggestions, but haven’t got to them yet.

 

Please make sure you have the latest version, thanks again

Download