Previous|Next

At Red Pill Development, Peter Presnell has encouraged our development efforts to use a "Mobile First" approach. The process is that you design your mobile interface first, get everything working properly and then move on from there to Tablet and then Web Browser interfaces re-using as much as possible from the previously working mobile implementation. This approach has several advantages:

  • It forces you to research, gather requirements and only display and write code for the things you actually NEED
  • The flow of the application will be defined by the mobile interface
  • It shapes the direction of the entire project
  • It forces you into thinking differently
  • Makes the next interface implementations easier

At first I fought this approach as it was easier for me to come up with a browser based solution quickly. But as we're progressing down this road, I'm finding that by doing Mobile First all of the hard stuff is already done by the time you get to the next implementation. You don't have to figure out where data is coming from, how it's being represented and how to handle the little issues that always seem to pop up. They've already been addressed in the Mobile site so they're usually already taken care of.

Another advantage of the Mobile First approach is that it buys time to experiment with different techniques and technologies. I say this because of how quickly a mobile interface can come together using the mobile components in the extension library. Are there shortcomings with these components? Sure there are, but they perform very well. These components can be extended and improved by taking advantage of the properties, methods and events from their original dojox widgets.

Now I know you're thinking... what about responsive design? Well, you're right to ask about that. Responsive design certainly has it's place and is very powerful and easy to implement. However if you start off with this approach you'll find yourself putting things in that you don't really NEED. You'll be designing for the browser and not the mobile device. Plus, it's certainly argumentative as to if it works well on a mobile device. Sure there are some sites that got it right, but there are some that don't. The counter argument would be that if you're intent on doing a responsive design that you start off designing for mobile first. This forces you to only include things on the screen that are needed.

While I know I've argued with myself here some, I hope I've made a point or at least put an idea in your head to at least try it on one project and see where it leads you. I bet you'll be pleased with the outcome.

Have you ever had a dream that you were so sure was real? Well today is the first step in realizing that dream.

A few months ago I made a post about being one of the co-founders for a new company called Red Pill Development. This company was founded on the controversial belief that modernizing Notes applications one at a time by reproducing all of the existing functionality is a loosing strategy.  In order to turn a profit modernizing applications, you have to do so en-masse and only include the features that are needed and being used. We came about this epiphany from attempting to reproduce Notes applications in their entirety and with all features functioning exactly as they had in the Lotus Notes client, and do this all automatically. To put this statement into perspective I had commented that Peter still had the "Yellow Books" around his office. He informed me that they were the specification for our previous project. 

So, after 6 months, much debate, pain, worrying and a lot of late night coding, the first step in our journey is now realized. We are now ready to start talking about the success that Red Pill Development has had at an actual customer site, and not just in a lab environment. In a joint effort with The Salvation Army we were able to implement our vision of "Asymmetric Modernization" in their environment by mobilizing 38 Notes applications in a single day.  The rest of the time was spent developing the platform, training their developers and documenting the process. To further prove the technology, we applied the same process to the Nifty Fifty applications provided in 1992 by Lotus. Doing this took about half an hour.

In that post I mentioned earlier, I stated....

No one can be told what Red Pill is. You have to be shown.

We are now ready to start showing what Red Pill is and what it can do for your organization. As of today, Red Pill Development is proud to announce that redpill Mobile is available for immediate deployment in your environment. Visit red-pill.mobi from your iOS or Android device to see the results of the mobilization of the Nifty Fifty. If you're interested in more information, take a look at our demo video and the case studies for the Nifty Fifty and The Salvation Army. If you would like to talk with us about implementing redpill Mobile in your environment, please contact us at info@redpilldevelopment.com.

Take the Red Pill.

At Red Pill Development we're pushing the envelope a bit on XPages Mobile, we're certainly pushing the mobile controls to their limits. Because of this sometimes we need to take matters into our own hands and override the XPages Mobile controls and kind-of take over how they operate or create our own.

One of the things you're going to encounter when you delve into XPages Mobile development is trying to put a Tab Bar at the bottom of the screen that actually stays at the bottom of the screen. We were able to incorporate this by implementing the Dojo ScrollablePane as a custom dijit. We needed to pursue this route as it had to work with Domino 8.5.3. If you're using Domino 9.0 presumably you can just change the dojoType of a div to "dojox.mobile.ScrollablePane", add the dojo resource and voila you're done. However, the ScrollablePane didn't come around until Dojo 1.8 and Domino 8.5.3 uses Dojo 1.6. 

So, to incorporate this I followed a post I did a while back on adding a custom dijit to an NSF. So once that was setup, I needed to hijack the Dojo 1.8 version of dojox.mobile.ScrollablePane. To do this you'll need to copy the files needed directly into the nsf. The files you'll need are:

  • dojox\mobile\Pane.js
  • dojox\mobile\ScrollablePane.js
  • dojox\mobile\_ScrollableMixin.js
  • dojox\mobile\scrollable.js
  • dojox\mobile\sniff.js

I copied all of those files including the directory structure into a folder I created in the WebContent folder called redpill. So we ended up with a directory structure of WebContent\redpill\dojox\mobile\*.js. We need all of those files because following what ScrollablePane.js extends that would be all of it's recursive dependencies. All of those particular files didn't show up until Dojo 1.8. The dependencies that were part of Dojo 1.6 you don't need to include here. You'll also need to go through all of those files and add redpill to the path and declared class to make it read redpill.dojox.mobile.* or redpill/dojox/mobile/*.

Theoretically all you should have to do now is create a div that will hold the content that you want within the ScrollablePane and give it a dojoType of "redpill.dojox.mobile.ScrollablePane". However you will run into some weirdness, as in nothing is displayed. So you'll have to extend the startup method from _ScrollableMixin.js inside the ScrollablePane.js file.

startup: function() {
	this.inherited(arguments);
	//Added by Red Pill Development to ensure that the control is actually created
	this.resize();
	//END RPD
}

Once that's done, you should get data within the scrollable pane. Now, to get the header and footer to stay where they should there are some properties of the ScrollablePane you can set that will lock the location of those elements. Those properties are:

  • fixedHeader - The client side ID of the header
  • fixedFooter - The client side ID of the footer
  • fixedHeaderHeight - The height in pixels of the header
  • fixedFooterHeight - The height in pixels of the footer

So, for your header and footer you should add those outside the div you gave the dojoType of redpill.dojox.mobile.ScrollablePane and you should end up with XSP markup something like the following:

<xe:appPage
	id="appPage1"
	pageName="firstpage">
	<xe:djxmHeading
		id="djxmHeading1"
		label="Scrollable Pane Demo">
	</xe:djxmHeading>
	<xp:div
		id="scrollableContent"
		dojoType="redpill.dojox.mobile.ScrollablePane">
		<xp:this.dojoAttributes>
			<xp:dojoAttribute name="fixedFooter">
				<xp:this.value><![CDATA[#{javascript:var mobFooter = getComponent("tabBar1");
	return mobFooter.getClientId(facesContext);}]]></xp:this.value>
			</xp:dojoAttribute>
			<xp:dojoAttribute name="fixedHeader">
				<xp:this.value><![CDATA[#{javascript:var mobHeader = getComponent("djxmHeading1");
	return mobHeader.getClientId(facesContext);}]]></xp:this.value>
			</xp:dojoAttribute>
			<xp:dojoAttribute
				name="scrollDir"
				value="v">
			</xp:dojoAttribute>
			<xp:dojoAttribute
				name="roundCornerMask"
				value="true">
			</xp:dojoAttribute>
			<xp:dojoAttribute
				name="radius"
				value="5">
			</xp:dojoAttribute>
			<xp:dojoAttribute
				name="fixedHeaderHeight"
				value="54">
			</xp:dojoAttribute>
			<xp:dojoAttribute
				name="fixedFooterHeight"
				value="54">
			</xp:dojoAttribute>
		</xp:this.dojoAttributes>
		<xe:dataView
			id="dataView1"
			pageName="secondpage"
			openDocAsReadonly="true"
			rows="30">
			<xe:this.data>
				<xp:dominoView
					var="defaultView"
					viewName="Default">
				</xp:dominoView>
			</xe:this.data>
			<xe:this.summaryColumn>
				<xe:viewSummaryColumn
					columnName="Title"
					columnTitle="Title"
					contentType="text">
				</xe:viewSummaryColumn>
			</xe:this.summaryColumn>
			<xe:this.extraColumns>
				<xe:viewExtraColumn
					columnName="UNID"
					columnTitle="UNID"
					contentType="text"
					style="font-size: 0.7em;">
				</xe:viewExtraColumn>
			</xe:this.extraColumns>
		</xe:dataView>
	</xp:div>
	<xe:tabBar
		id="tabBar1"
		barType="segmentedControl">
		<xe:this.dojoAttributes>
			<xp:dojoAttribute
				name="center"
				value="true">
			</xp:dojoAttribute>
		</xe:this.dojoAttributes>
		<xe:tabBarButton
			id="tabBarButton1"
			label="Button 1">
		</xe:tabBarButton>
		<xe:tabBarButton
			id="tabBarButton2"
			label="Button 2">
		</xe:tabBarButton>
	</xe:tabBar>
</xp:appPage>

I've created a demo db for this which you can find here. The demo db is also attached to this post but isn't quite the same, it's missing the "Short View" that only shows a few documents. This view shows that by using the Scrollable Pane forces your footer to be at the bottom. But you should be able to get the idea from the attached demo db. There is a bonus in the attached demo however and that's the infinite scroll custom control which the Javascript that actually fires the scroll is incorporated into Scrollable.js in the adjustDestination function. Enjoy.

Here lately, I've been working on getting events to fire within a mobile application in XPages. For example when a page first loads (i.e. is navigated to but not "transitioned" to) or when a transition/navigation to another page within the single page application. No events are published or made available via the domino designer IDE but we still need to be able to do something when a navigation/transition event happens. So, how do we do this and what are the event names? Well the dojo event names are:

  • onStartView - Only works with Domino 9 or Dojo 1.8
  • onBeforeTransitionIn
  • onAfterTransitionIn
  • onBeforeTransitionOut
  • onAfterTransitionOut

These events should provide you a means to run client side javascript or make a call to an RPC to run some SSJS or as an entry point into java. After I started putting together the simple demo for this db I found an OpenNTF XSnippet from Tony McGuckin outlining this process, however his doesn't show using dojo.subscribe but does show how to incorporate an RPC into your page to handle SSJS functionality.

To use these events, simply add an <xp:scriptBlock> to the bottom of your page outside the Single Application Page. Here's the CSJS inside the script block:

dojo.addOnLoad(function(){
    //NOTE: "home" is the name of the app page
    var page = dijit.byId("home");
    dojo.connect(page, "onBeforeTransitionOut", function() {
        console.log("onBeforeTransitionOut fired", arguments);
    });
});

Now, when you moveTo a different page from the "home" page you should see your console.log message show up in the javascript console. I could not get onStartView to work using dojo.connect, so if you can get that to work, please let me know.

If you're running Domino 9 or have ported Dojo 1.8 to run on your older version of Domino you can also subscribe to events. dojo.subscribe is a listener for events (please correct me if I'm misunderstanding dojo.subscribe on this point) that would make it easy to incorporate your own CSJS API as this is a listener for that event on all DOM elements, not for a specific DOM element like using dojo.connect. However, this technique only works in Domino 9 or Dojo 1.8.

dojo.subscribe("dojox/mobile/beforeTransitionOut",function() {
    console.log("beforeTransitionOut fired", arguments);
});

Hopefully this will give you a means of adding some additional events to your mobile applications.

EDIT: I forgot the Demo. Hopefully I'll find a way to add demo databases to the posts again.

So today while looking for a solution to handling an HTML5 event of onSearch I came across this technique, which, probably isn't the best approach but does work. So, if you look at the client side events of an inputText field, you'll notice there isn't an event for onSearch. So, how do you add one? Well, you could of course go pass-thru html and just code the field as you would a Plain Jane HTML field. While this would work, to me it's just not taking advantage of the platform and wouldn't allow you to compute any of the other attributes.

So to address this issue we add an attribute to the field with a name of onsearch and then for the value, we write some SSJS that returns CSJS. I generally don't like doing this as it just feels dirty, but it does work in a bind. So to test this, here's the XSP markup for an inputText field using this technique.

<xp:inputText
    id="someField"
    value="#{document1.description}">
    <xp:this.attrs>
        <xp:this.attr
            name="onkeyup">
            <xp:this.value><![CDATA[#{javascript:return "alert('onkeyup fired');";}]]></xp:this.value>
        </xp:this.attr>
    </xp:this.attrs>
</xp:inputText>

Now when you put the cursor in the field and press a key and release it, you'll get the CSJS Alert box. Surprisingly this does work and I hope you can get some mileage out of it. Happy coding.

Wouldn't it be cool if we could integrate some off the wall feature into our XPages environment? This is a phrase that gets used quite a bit in the team I work with and I think is a key driver to innovation, discussion and a source of producing excitement about whatever followed that phrase. While the phrase itself isn't very awe inspiring or really doesn't mean that much, I do think it is a key player in driving innovation. Some examples if you please....

  • Wouldn't it be cool if... there was technology that would take a Notes application and spit out an XPages application? (Been there done that and now we know the answer that it's too expensive)
  • Wouldn't it be cool if... we could know how our users are using Notes applications?
  • Wouldn't it be cool if... we could figure out how applications are related to one another?
  • Wouldn't it be cool if... we could figure out who our subject matter expert is for any given Notes application?
  • Wouldn't it be cool if... we could figure out what bits of code are the most used in form actions?
  • Wouldn't it be cool if... we could figure out where all the instances of a given application are located within our entire Domino infrastructure?
  • Wouldn't it be cool if... we could come up with a better way to modernize a notes infrastructure?

These are but a few of the "Wouldn't it be cool if...." discussions that have lead to products, a new company and driving innovation on an unbelievable scale and that I personally have been involved with. It's these questions that make you think of the possible and come up with creative ways to address the question. Usually the answers are quite stark and certainly creative.

It's just such a simple phrase that can drive so much, which is what makes it kind of mind-blowing when you think about it. There is currently a car commercial featuring this phrase (I can't think of the company off hand). Every time I see that commercial it makes me think of this and how we use it on almost a daily basis. What will really blow your mind is what phrase was used before the word "cool" was... well.... cool and meant something other than chilled? I don't know, but I'm sure it probably had the same results (i.e. Wouldn't it be cool if we could go to the moon, put a spacecraft in orbit, send a probe into deep space?).

While XPage and Java development probably isn't as difficult as rocket science it still is a very good space for innovation, thinking outside the box and being creative. So I post this question to you now dear reader.... when was the last time you asked a team mate(s) this question.... Wouldn't it be cool if....(insert your cool idea here)? If you can't remember, why not make it a habit of asking that question in your next team meeting, round table, smoke break, lunch break or whatever break? What can it hurt? It just might lead to something earth shattering.

As you might or might not have known, I've been striving for a calendar in XPages since XPages were introduced. I created the XPages Calendar project which was a poor attempt at building a calendar. When I built it the extensibility API was not available and neither was the Extension Library. So, while it basically worked, it was not a very elegant implementation, especially the data handling.

I recently had a need for a calendar implementation that met a few different criteria:

  1. Must be responsive
  2. Must work in a mobile interface
  3. Must be functional and offer Month, Week and Day views
  4. Must be able to feed it events via REST

In steps the jQuery Plugin called FullCalendar. This plugin seems to be very solid. It works well in the Extension Library mobile components, can get it's content via REST and has all the views above plus a couple of others. This plugin has been a joy to work with and produces some rather nice looking calendars on a full on browser, phone and tablet, which is certainly a bonus.

To implement this calendar is quite simple and just takes a bit of CSJS to make it work. Here is an example of the REST calendar in the demo db.

var calCon = $("[id$=calendarContainer1]");
var urlVal = function() {
    var baseUrl = location.href;
    var restUrl = baseUrl.substring(0, baseUrl.indexOf(".xsp") +4);
    restUrl = restUrl + "/calendarData";
   return restUrl;
}
calCon.fullCalendar({
    firstDay: 0,
    header: {
        left: "prev,next today",
        center: "title",
        right: "month,basicWeek,basicDay"
    },
    disableDragging: true,
    events: {
        url: urlVal(),
        type: "GET",
        error: function() {
            alert("something asploded");
        }
    },
    dayClick: function(date, allDay, jsEvent, view) {
        console.log("date=",date);
        console.log("allDay=",allDay);
        console.log("jsEvent=",jsEvent);
        console.log("view=",view);
    }
});

But take a look at the demo I put together here. I think you'll like it. It seems that I'm not able to attach files which is probably a permissions issue, but when I get that rectified I'll be sure and attach that demo db here.

I've been doing a lot of development work here lately, I mean a lot. Looking at different technologies and implementing them into XPages or at least attempting to. One of my tasks was trying to learn about OAuth and working with connections. I downloaded and installed the IBM Social Business Toolkit and SDK. I then followed several tutorials out on the web (most of them from IBM) trying to authenticate to GreenHouse with no luck. I ran into issue after issue. I got it all the way to being asked to login by GreenHouse and was given some "rotating outage" error message. Well, that can't be right, GreenHouse is up. So I reached out to a couple of different IBMers trying to determine what I was doing wrong. I spent several days on this and was at my wits end. Lastly I spoke with Niklas and was informed that the public OAuth for GreenHouse was currently not enabled. This really baffled me and actually made me quite angry. What made me angry I guess was that all of these tutorials, the SBT documentation and various other documentation explaining how to get a token from GreenHouse was all from IBM. The error messages are quite cryptic as to what the problem was or in some cases wasn't.

So, with that background, on to my request.... IBM, why or why can't you provide a friendly error message? I spent days trying to get something to work that wasn't even turned on. Why not inform me via an error message that this feature is currently disabled? Don't get me wrong here, I'm not complaining about the service being disabled. I have no problem with a service being disabled because it's not ready for prime time yet or because of some other matter. Just let me know before I spend days trying to determine why it's not working.

Rant Off

I am proud to announce that keithstric.com has been moved back to Prominic. Prominic is an excellent host for all types of domino sites. If you're in the market for a new web host, take a look at Prominic. Their service and support is top notch and second to none.

I've learned my lesson and won't be moving this blog again. Now, I've just got to get all the different aggregators looking at keithstric.com instead of xprentice.gbs.com.

I've recently started playing with a very powerful Javascript library called D3.js. D3 is for visualizing data either in charts, force layout graphs, data plots or whatever you can imagine. I'm not really sure what the point of this post is as I really can't show you yet what we're using it for. But I can show some of the things that it's capable of.  

Let's first look at a Force Directed Layout. These are usually used to show hierarchical data and the way D3 handles them is very cool looking. You can also include labels, pop ups, etc for the nodes on the plot. If you're really interested in this you can find all kinds of examples.

Next up is charts. D3 makes some beautiful charts that are interactive and zoomable. 

D3 is also capable of Geo Spatial type visualizations, showing data based on a location and some of these are very cool, with spinning globes and such. I saw one in a video that was generating random plots on the spinning globe but can't seem to find it. One of the best I've seen is the NY Times depiction of the Election Results down to the county level of the entire U.S.

Here are a few other cool visuals

D3 excels at animating data in a visually pleasing way. If you have static data, it can represent that, but that's not where it excels. Also, the learning curve is quite steep, well more like a brick wall. The main concept in D3 is you tell it what to do with data as it's made available. One of the speakers I listened to said

If you're looping over data in D3, then you're doing it wrong. 

D3 visualizations are placed on an SVG area and then you place circles, rectangles, images, icons, etc. on that SVG area and define what to do with them when a new one arrives. You don't have to figure out the x,y coordinates yourself, let the platform handle that for you.

If you need to represent data visually then I highly recommend you take a look at D3.js. To get started take a look at their tutorials section. There are many good resources there to get you up and running quickly. While I am certainly no expert on D3 I have recognized that it's very powerful, stable and quick to use. Most of the visualizations I've done only took a day or less and they came out looking quite nice. I will admit  that my first ones looked horrible, but with practice they get nicer and nicer. There also seems to be a fairly active community on StackOverflow if you get stuck.

Page12345678...