Auto-focus – Do it! It’s just lazy not to.

In this article I will discuss the need as a developer to use an auto-focus on your XPages. You do this when the end-user needs to type something onto your webpage and should not have to use their mouse to click in the field first.

Introduction

You’ve been there – you go to a website internal or external to your company and you have to login in or type something into the page – the search field or something of that ilk. It is the only field on the whole page and you have to use your mouse to focus on the field – frustrating beyond belief and quite frankly, lazy on the part of the developer. It is a pet peeve of mine when something as simple as one line of code can make a big difference to the first thing a user does on your site.

Can you imagine going to Google.com and having to focus on the field to get started on your search? Stupid idea – or so you would think.

Login Pages

The login page is perhaps the most obvious thing – as the developer you should ALWAYS focus on the username field – it is just lazy not to! It is harder on the user to have to click in the field and they are entering your website with an irritation on their mind already.

Auto-focus on the Username field
Auto-focus on the Username field

 

So how do we do this?

Well it depends on what takes your fancy that day…..but this is normally something you would do within some <script> tags on your web page.

Using the plain old JavaScript method

  document.getElementById("username").focus()

In Dojo

  dojo.byId("username").focus()

In jQuery

  $("#username")[0].focus()

NOTE

We use the [0] to get the DOM Node element and use the HTML focus() method
.focus() when applied to a jQuery object is an event handler which determines what happens when you focus on something  – be careful to use correctly

$('#target').focus(function() {
  alert('Handler for .focus() called.');
});

In HTML5

The autofocus attribute of a field is new in HTML5 (thanks to David Walsh). You can also focus on a button and other DOM objects

<input autofocus="autofocus" />
<button autofocus="autofocus">Hi!</button>
<textarea autofocus="autofocus"></textarea>
Advertisements

Stencil.js – (Applying a transparent CANVAS mask) – I need some suggestions

In this article I am going to show you how I created stencil.js – A technique for making a transparent mask on top of an image. But I am a little lost as to what to do with the technique now I have created it – any suggestions would be gratefully received and much appreciated.

Example

So I have been working on this idea for a couple of weeks and I finally figured out how to make the technique work whereby you can draw a picture ontop of a web font text (or make it look like that anyway)

Drawing a picture on top of web based text
Drawing a picture on top of web based text

I think it is kinda cool – shame the font has sharp edges and isn’t feathered but hey.

How does it work?

So what I am actually doing is taking an image

An image
An image

Drawing a “<CANVAS>” element on top of it and writing some text onto the canvas (so no IE)

Writing some text onto the canvas
Writing some text onto the canvas

Then I make all the red pixels on the canvas have opacity=0 (i.e. see through) and everything else color white with opacity 255 (not see through)

It is easier to see the effect if I make the white canvas slightly opaque – in this image you can JUST see the original as I have set it to 225 not 255.

This canvas manipulation was what I found Patrick Wied had used in making the watermark.js plugin which I wrote about earlier in the year. Each pixel in the canvas can be manipulated with the RGB value and Opacity – so I can make anything white and or transparent.

If you want to see it in actiion go to the jsFiddle I have created: http://jsfiddle.net/mdroden/aefh4/

Or if you think you can improve it – git it – https://github.com/markyroden/stencil

So I need suggestions….

The plan is to turn this into a jQuery plugin – but for what purpose? Other than a demonstration of it can be done – what’s the good practical usage for it. And then from that what variables are required to make the end result work?

In the jsFiddle example I pass in the Text, font and font-size. But there are also some tweaking to be done to position the text optimally over the image – and this varies based on the font and the size. I used Fascinate because it was a “fat” font and therefore showed a lot of the background image……Probably the transparency of the “white” mask could be a variable as well.

I am thinking something like this


$('#image').stencil({
	text: 			"XOMINO",
	font-family: 	"fascinate",
	font-size: 		70,
	text-positionX:	10,
	text-positionY:	30,
	text-color:	"red",
	mask-opacity:	255
}

I have a lot of balls in the air what with MWLUG and a new job in the offing but I will come back to this and at least make a basic plugin for it….

So how would you use it?

Marky

Pushing data to an XPage from the server – HTML5 eventSource

Introduction

We are going to look at the new HTML5 eventSource capability. Adapting the articles (posted here) and (posted here) I am goign to show you how to send data from the server to your XPage without using ajax to initiate the communication. I have the feeling there is a lot to learn in this area and we are just scratching the surface.

Browser Support

Yep – it is HTML5 which means no IE right now – Chrome should support this but my copy does not – so right now this demonstration is only tested and working in the latest version of FireFox.

Demonstration

The results of this article are demonstrated here, and I strongly suggest you use some kind of plugin to watch the traffic as the values chance – quite fascinating. Right click – View Source and see for yourself – no ajax! no jQuery, nothing fancy, just HTML5 in action!

http://demo.xomino.com/xomino/xPlay.nsf/xHTML5ServerSent.xsp

Server output

I have modified Stephan Wissel’s xAgent XSnippet to create a simple data stream using server-side output. Calling this xAgent through the web generated the following simple data output as seen here through Firefox HTTPFox plugin.

The thing to highlight is the Content-Type text/event-stream

xAgent output
xAgent output
<?xml version="1.0" encoding="UTF-8"?>
<!-- XPage which is not rendered but returns data like XML, JSON, etc.     -->
<!-- More: http://www.wissel.net/blog/d6plinks/shwl-7mgfbn                 -->

<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
  <xp:this.afterRenderResponse>
	<![CDATA[#{javascript:
		var externalContext = facesContext.getExternalContext();
		var writer = facesContext.getResponseWriter();
		var response = externalContext.getResponse();

		// set content type, e.g. ...
		response.setContentType("text/event-stream");

		response.setHeader("Cache-Control", "no-cache");

		// read parameters, e.g. ...
		var param = context.getUrlParameter("myParam");

		// write HTML output e.g. ...
		writer.write("data: the number is "+@Random());

		writer.endDocument();
	}]]>
  </xp:this.afterRenderResponse>
</xp:view>

HTML5 JavaScript

In our xPage we create some JavaScript to instantiate and then listen to the eventSource
First of all we test to see if the EventSource is supported in this browser

		if(typeof(EventSource)!=="undefined") {

		else {
			dojo.byId("#{id:serverData}").innerHTML="Whoops! Your browser doesn't receive server-sent events.";
		}]]>

Using the following code we subscribe to the EventSource (xSendHTML5Data_1.xsp is the xPage described above)

			var eSource = new EventSource("xSendHTML5Data_1.xsp");

And then when we receive a message from the server we act on it

			eSource.onmessage = function(event) {
				//write the received data to the page
				dojo.byId("#{id:serverData}").innerHTML = event.data;
			};

This all comes together as the following ScriptBlock in the page

	<xp:scriptBlock id="scriptBlock1">
		<xp:this.value><![CDATA[//check for browser support
		if(typeof(EventSource)!=="undefined") {
			//create an object, passing it the name and location of the server side script
			var eSource = new EventSource("xSendHTML5Data_1.xsp");
			//detect message receipt
			eSource.onmessage = function(event) {
				//write the received data to the page
				dojo.byId("#{id:serverData}").innerHTML = event.data;
			};
		}
		else {
			dojo.byId("#{id:serverData}").innerHTML="Whoops! Your browser doesn't receive server-sent events.";
		}]]>
		</xp:this.value>
	</xp:scriptBlock>

Stopping the source

We are able to stop the source using eSource.close() that will stop the data being sent. I added mine in a button

	<xp:button id="button1" value="Stop the Source">
		<xp:eventHandler event="onclick" submit="false">
			<xp:this.script><![CDATA[eSource.close()]]></xp:this.script>
		</xp:eventHandler></xp:button>

Changing the refresh time

We are able to change the refresh time by returning the retry value in millisecond along with our data

writer.write("retry: 2000\ndata: the number is "+@Random());
setting the refresh time 2000ms
setting the refresh time 2000ms

Specifying an event name

This mercilessly ripped directly from the article – I have not done anything with the event listeners yet, but here the next thing I want to look at….using the data returned from the server to trigger events in the browser without having to parse the return string and take action on it – that’s a huge performance gain and distributes the tasks….more to come on that in the near future….

For example, the following server output sends three types of events, a generic ‘message’ event, ‘userlogon’, and ‘update’ event:

data: {"msg": "First message"}\n\n
event: userlogon\n
data: {"username": "John123"}\n\n
event: update\n
data: {"username": "John123", "emotion": "happy"}\n\n
With event listeners setup on the client:

source.addEventListener('message', function(e) {
  var data = JSON.parse(e.data);
  console.log(data.msg);
}, false);

source.addEventListener('userlogon', function(e) {
  var data = JSON.parse(e.data);
  console.log('User login:' + data.username);
}, false);

source.addEventListener('update', function(e) {
  var data = JSON.parse(e.data);
  console.log(data.username + ' is now ' + data.emotion);
}, false);

Enjoy 🙂

Demonstration

http://demo.xomino.com/xomino/xPlay.nsf/xHTML5ServerSent.xsp

QR code with your picture in it !

While researching the next jQuery in XPages article I came across a QR code designer page which allows you to add your own image into the code itself.

http://www.patrick-wied.at/projects/qr-designer/

You need to use the latest Chrome or FF browsers to get the full effect as he uses Drag and Drop to pull in the image but you can make something like this – how cool is that !!

QR code with your truly in the picture
QR code with Marky in the picture

HTML5 drag and drop demonstration in an XPage

I saw an article on HTML5 drag and drop and wondered how hard it would be in XPages.

Demonstration

Here is a link to the working demo of HTML5 drag and drop in an XPage – this is FF and Chrome only as drag/drop is not supported until IE10

How does it work?

I created an XPage and added a simple data table

Data Table
XPages Data Table

Going off the text in the article I tried to add the events to the Fruit label column – unfortunately you cannot add custom attributes to an xp:text

Cannot add custom attributes to an <xp:text
Cannot add custom attributes to an <xp:text

So once again – back to using dojo selectors to get what we want.

The HTML generated by the XPage creates all the fruit labels (Oranges, Bananas, Apples) with an id=blah:_1blah ending in “someFruit”

<tr><td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:0:column3:someFruit" class="xspTextComputedField">Oranges</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:0:column1:computedField2" class="xspTextComputedField">2.0</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:0:column2:computedField3" class="xspTextComputedField">4</span></td>
</tr>
<tr><td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:1:column3:someFruit" class="xspTextComputedField">Bananas</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:1:column1:computedField2" class="xspTextComputedField">1.0</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:1:column2:computedField3" class="xspTextComputedField">2</span></td>
</tr>

We can get a handle on these labels using dojo.query(“[id$=someFruit]”) which will get all elements with an id attribute ending in “someFruit”

Once we have all of those elements we can add a draggable and ondragstart attribute to them easily using dojo.attr

			dojo.query("[id$=someFruit]").forEach( function(node){
				 dojo.attr(node, "draggable", "true");
				 dojo.attr(node, "ondragstart", "dragIt(event);");
			});

Update – Thanks to Tim Tripcony for pointing this out
If you are using 8.5.3 you can add the custom attributes to the field in the designer client. This removes the need to use the dojo.query

<xp:text escape="true" id="someFruit" value="#{colname1.Fruit}" style="color:rgb(0,0,255)">
	<xp:this.attrs>
		<xp:attr name="ondragstart" value="dragIt(event);"></xp:attr>
		<xp:attr name="draggable" value="true"></xp:attr>
	</xp:this.attrs>
</xp:text>

Then we just need somewhere to drop them…
I added the same DIV elements from the example to the XPage

				<xp:td>
					<div id="place1" ondrop="dropIt(event);"
						ondragover="event.preventDefault();">
					</div>
				</xp:td>
				<xp:td>
					<div id="place2" ondrop="dropIt(event, true);"
						ondragover="event.preventDefault();">
					</div>
				</xp:td>

and added the javascript functions to a scriptblock at the bottom of the page

	//function called when drag starts
		function dragIt(theEvent) {
			//tell the browser what to drag
			theEvent.dataTransfer.setData("Text", theEvent.target.id);
		}

		//function called when element drops
		function dropIt(theEvent, keepMe) {
			//get a reference to the element being dragged
			var theData = theEvent.dataTransfer.getData("Text");
			//get the element
			var theDraggedElement = document.getElementById(theData);

			//add it to the drop element
			if (keepMe){
				//Add a clone of the element to the field - rather than move it
				var newObj=dojo.clone(theDraggedElement)
				theEvent.target.appendChild(newObj);
			} else {
				theEvent.target.appendChild(theDraggedElement);
			}
			//Add a new line for visual line up
			var theBR=document.createElement("br")
			theEvent.target.appendChild(theBR);
			//instruct the browser to allow the drop
			theEvent.preventDefault();
		}

I changed the example slightly to add a clone capability rather than just drag and drop

Drag and Drop example 1
Drag and Drop example 1 (Move)

Dragging to the first box “moves” the label

Drag and Drop example 2 (Clone)
Drag and Drop example 2 (Clone)

Dragging the label to the second box create a copy of it using dojo.clone(node)

Conclusion

This is merely a prototype but demonstrates nicely the new and exiting capabilities of HTML5 without having the need for a dojo or jQuery library to do the drag/drop for you

Demonstration (again)

Here is a link to the working demo of HTML5 drag and drop in an XPage