ShowTable of Contents
Include Dojo libraries
To use certain dojo functionalities like the dijit.dialog you have to inlcude them in your XPage, see http://www-10.lotus.com/ldd/ddwiki.nsf/dx/Client_Side_JavaScript_Libraries_in_XPages.htm
.
In short: add a new resource "dojo module" to your XPage and enter the name of the dojo module.
Execute your code after page loads
Do NOT place some script somewhere in your page with uses dojo features in the hope that your scripts runs after the page is loaded.
You have to use dojo.addOnLoad() for that purpose:
<script type="text/javascript">
var init = function() {
alert("my own code which uses dojo stuff and should be executed after the page was loaded");
}
dojo.addOnLoad(init);
</script>
You should place this code somewhere at the bottom of your XPage or custom control (to be exact, it just needed to be executed after the dojo core was loaded).
Accessing DOM nodes
Use dojo.byId() to get some element like a DIV or an input field or a list item.
XPages elements (like a panel or an input field) have an ID (=name in the XPage editor). Unfortunately, you cannot access these elements by these IDs in dojo client scripts. That's because the name of a XPage component is dynamically prefixed with other stuff at runtime before becoming an ID (look at the source of a XPage in the browser!).
In events of XPage components you can use "#{id:XPage component name}", which will be replaced by the actual ID of that component at runtime.
Example: create a panel and give it the name "myPanel". Create a button and in the on click event write:
dojo.byId("#{id:myPanel}").innerHTML = "found it!"
Accessing XPage components in all kind of client scripts
The "#{id:...}" construct does not work for example in client side javascript libraries.
There you can se a CSS selector with dojo.byId() like this:
elem = dojo.query("[id$='myPanel']")[0];
elem.innerHTML = "found it with by using a CSS3 selector"
dojo.query() returns an array (!) of DOM nodes by using CSS 3 selectors (see www.w3.org/TR/css3-selectors). Because it's an array, you need "[0]" to access the first element of it.
More about accessing nodes with a query
Some common usages of dojo.query():
dojo.query("div") ' returns all div elements
dojo.query("div[id='one'])[0] ' returns the div element with id "one"
dojo.query("div.someClass") ' returns all divs having the css class "someClass"
dojo.query(".someClass") ' returns all elements having the css class "someClass"
dojo.query("div[id*='someid']) ' returns all divs having an id in which "someid" occurs
dojo.query("[id$='someid']) ' returns all divs having an id which ends on "someid"
dojo.query("[id^='someid']) ' returns all divs having an id which starts with "someid"
Type checking
Use the following functions to check if a variable has a certain type:
isString(value)
isArray(value)
isFunction(value)
isObject(value) ' true for an object, including Array, Function or null
String utilities
Trim a string:
dojo.trim(s)
Fill up a string:
dojo.string.pad(s, count, char)
Substitution:
dojo.string.substitution("here is one param ${0} and here is another ${1}", ["param1", "param2"])
Array processing
No, Array.indexOf is NOT supported in all browsers. Use dojo instead:
Get index of one element:
dojo.indexOf(array, element, startIndex)
Get last index:
dojo.lastIndexOf(array, element, startIndex)
Check if all elements of an array fits a condition:
dojo.every(array, function(x) {return x == y}) ' returns true if all elements in the array are equal to y
Iterate over elelents:
dojo.forEach(array, function(x) {do something with x})
Transform elements:
dojo.map(array, function(x) {return x + 1}) ' increments all elements of the array by 1
Filter elements out of an array:
dojo.filter(array, function(x) {return x == y}) ' leaves all elements in the array which are equal to y
Modify HTML of an element
dojo.byId("#{id:someXPagePanel}").innerHTML = "some html";
dojo.byId("someOtherHTMLElement").innerHTML = "some html";
Modify the style of an element
Example: hide div with the id 'mydiv':
dojo.style(dojo.byId('mydiv'), {display: 'none'});
Add a CSS class to an element:
dojo.addClass(dojo.byId('mydiv'), 'someCssClass');
Remove a CSS class from an element:
dojo.removeClass(dojo.byId('mydiv'), 'someCssClass');
Get position of one element and set the position of another element
var pos=dojo.coords("elementid", true);
dojo.byId("#{id:otherelement}").style.top = (pos.y+20)+"px";
dojo.byId("#{id:otherelement}").style.display = "block";
pos.x=position from the left
pos.y=position from the top
pos.w=width of the element
pos.h=height of the element
dojo.coords(param1, param2) -> param2=true -> include scrolling in height, param2=false -> compute height without scrolling
Use specialized input elements
NumberSpinner
You can convert an edit box to a dojo number spinner by writing this code in the source of the XPage, at the end:
<script type="text/javascript">
var f = function() {
elem = dojo.query("[id$='tmpNr']")[0];
v = elem.value;
var d = new dijit.form.NumberSpinner({constraints:{min:1,max:999},style: "width:55px;"}, elem)
d.setValue(v);
}
dojo.addOnLoad(f);
</script>
Replace "tmpNr" with the name of your edit box.
See http://www.dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/form-validation-specialized-input/number-spinner
for more information about the NumberSpinner.
Slider
You can use the dijit.slider to push number values to a XPages edit box, from where you do further processing.
A slider looks like this:

Add the "dojo.form.Slider" module to your XPage:

The slider itself is wrapped into a div tag like this:
<div id="horizontalSlider" dojoType="dijit.form.HorizontalSlider" value="7"
minimum="1" maximum="90" discreteValues="90"
intermediateChanges="false" showButtons="false"
onChange="dojo.query('[id$=sliderValue]')[0].value = arguments[0];
dojo.query('[id$=bRefreshView]')[0].click()"
style="width:250px">
<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration"
style="height:1em;font-size:75%;color:gray;">
<li>Label 1</li>
<li>Label 2</li>
<li>Label 3</li>
<li>Label 4</li>
</ol>
</div>
Attributes in the div tag:
value: the default value
minimun: minimum value of the slider
maximal: maximum value of the slider
intermediateChanges: set to true if the onChange event should run on every mouse movement of the slider, the to false if onChange should only run after the user moved the slider and releases the mouse.
showButtons: set to true if you want up/down buttons
onChange: Client JavaScript to execute, the slider value is in "arguments[0]"
You need to store the slider value into a XPage control.
Create an edit box with code like this:
<xp:inputText id="sliderValue" value="#{sessionScope.sliderValue}" style="display:none">
</xp:inputText>
Note the first element in the javascript in the onChange event of the div:
dojo.query('[id$=sliderValue]')[0].value = arguments[0]
This gets the DOMNode of our edit box and stores the slider value in it. You can make that visible if you remove "display:none" from the edit box's style.
And finally, you can even do a page refresh if the slider's value changed. For that, we need help from a hidden button:
<xp:button value="Label" id="bRefreshView" style="display:none">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial" id="eventHandler8" refreshId="viewPanel">
</xp:eventHandler></xp:button>
Note the "display:none" style, remove it when you want to see the button.
The second part of the div's javascript clicks that button when the slider changed:
dojo.query('[id$=bRefreshView]')[0].click()
In a nutshell, the logic goes as follows:
- user changes slider
- onChange event runs and executes the javascript
- first part of the javascript stores the slider's value into the XPage edit box
- second part clicks the hidden button to do a page refresh so that you can react on the changed value to, for example, filter a view by using a fulltext search.
Note: this works in Notes 8.5.1 or higher. For 8.5.0 you are not allowed to use the dojoType attribute in the div tag.
Create effects
fadeIn a div
- create a div
- set css of that div to "opacity:0" and "filter:alpha(opacity=0)"
In the Client JS (!) of for example a button you can use
var fadeIn = dojo.fadeIn({node: "#{id:mydiv}",duration: 250});
fadeIn.play();
wipe in and other animations
Note: you need to include the dojo.fx package in your XPage (all properties -> resources -> add DojoModule -> "dojo.fx"
- create a div
- set css of that div to "display:none" as INLINE css as follows:
<div id="mydiv" style="display:none">some content</div>
Important! Use "style=..." to define the display:none property, do not write that in an external CSS file or the animation will not work (bug in Dojo).
Then use the following client Javascript to wipein:
dojo.fx.wipeIn({node:'mydiv',duration:1000}).play();
other nice effects working the same
- wipeOut
- slideRight: dojo.fx.slideTo({node: "animDiv",duration: 1000, left: 300, top: 80});
- slideLeft: dojo.fx.slideTo({node: "animDiv",duration: 1000, left: 0, top:80});
combine effects
var fadeOut = dojo.fadeOut({node: "animDiv",duration: 1000});
var wipeOut = dojo.fx.wipeOut({node: "animDiv",duration: 1000});
var slideRight = dojo.fx.slideTo({node: "animDiv",duration: 1000, left: 300, top: 80});
dojo.fx.combine([fadeOut, wipeOut, slideRight]).play();
do something after the effect has played
You can execute some function after an effect (like the fadeIn) has played:
var fadeIn = dojo.fadeIn({
node: "#{id:mydiv}",
duration: 250,
onEnd: function() {
alert("effect finished!");
}
});
fadeIn.play();
There are more events:
beforeBegin: runs before the animation starts (synchron)
onBegin: runs after animation started (asynchron)
onPlay: runs while the animation plays (synchron)
onAnimate: runs for every step of the animation
Work with events
You can use Dojo to connect to events (like onclick or mouseover), which makes handling events easier.
1.) connect to an event
dojo.connect(elem, "eventname", function (e) { ...code... })
2.) using event's properties in your function:
connect to the event like this:
function myEventFunction(someparam, event) {
...code...
}
dojo.connect(dojo.byId("myid"), "onlick", function (e) { myEventFunction("someparam", e); })
Then you can use the following properties of the event object:
- event.target - the element that generated the event
- event.currentTarget - the current target
- event.layerX - the x coordinate, relative to the event.currentTarget
- event.layerY - the y coordinate, relative to the event.currentTarget
- event.pageX - the x coordinate, relative to the view port
- event.pageY - the y coordinate, relative to the view port
- event.relatedTarget - For onmouseover and onmouseout, the object that the mouse pointer is moving to or out of
- event.charCode - For keypress events, the character code of the key pressed
- event.keyCode - for keypress events, handles special keys like ENTER and spacebar.
- event.charOrCode - a normalized version of charCode and keyCode, which can be used for direct comparison for alpha keys and special keys together. (added in 1.1)
(taken from Dojo campus
)
3.) events you can connect to
- onclick - the user clicked a node
- onfocus - a node received focus
- onblur - a node was 'blurred', or otherwise lost focus
- onchange - an input value was changed
- onkeypress - fired when the user presses a key
- onkeydown - shouldn't be necessary to be used... all key presses go to onkeypress
- onkeyup - fired when the user releases a key
- onmouseover - a node was hovered (warning: may fire more than you'd like because of bubbling)
- onmouseout - a node was un-hovered
- onmouseenter - a normalized version of onmouseover that wont fire more than you'd like (only on first enter)
- onmouseleave - a normalized version of onmouseout that wont fire more than you'd like (only once when leaving)
- onsubmit - a form has been submitted
4.) especially useful: onmouseenter, onmouseleave
Using mouseover/mouseout has it's problems when you use them on an element which contains other elements. The dojo "onmouseenter" / "onmouseleave" do what you expect: they fire when the mouse goes in the area of an element, and when it leaves that area (while mouseover / mouseout may fire again and again and again while the mouse moves in the element's area).
Use a panel as dijit Dialog
1.) Create a panel on your XPage.
2.) In the source view, wrap the <xp:panel>...</xp:panel> tags with:
<div id="myDialog" style="display:none">...</div>
3.) Put the following function in some client javascript library:
function dialog_create(id) {
var dialogWidget = dijit.byId(id);
if( dialogWidget ) dialogWidget.destroyRecursive(true);
dialogWidget = new dijit.Dialog( { }, dojo.byId(id));
var dialog = dojo.byId(id);
dialog.parentNode.removeChild(dialog);
var form = document.forms[0]; form.appendChild(dialog);
dialogWidget.startup();
}
4.) At the end of your XPage, put this javascript:
<script>dojo.addOnLoad(function() {dialog_create("myDialog")}):
5.) Open the dialog with
dijit.byId("myDialog").show();
6.) Inside your dialog's panel you can put a button to hide the dialog with:
dijit.byId("myDialog").hide();
(thanks to Mark Hughes for the dialog_create function!).
BACKGROUND:
You can add a 'dojoType="dijit.Dialog"' to your xp:panel tag, and this will create a dojo Dialog - but then you cannot work with fields and partial updates inside that dialog. That's because dojo moves the dialog's div into another context (to be exact: out of Domino's <form> element).
The dialog_create function gets the dialog's div and adds it back to a place into the DOM tree where Domino can "see" it.
Tooltips
You can use the dijit.Tooltip, see Dec's posting here: http://www.qtzar.com/blogs/qtzar.nsf/d6plinks/DSLH-7TWNY2
Basically, it's quite simple:
1.) include the dojo module "dijit.Tooltip":
<xp:this.resources>
<xp:dojoModule name="dijit.Tooltip"></xp:dojoModule>
</xp:this.resources>
2.) write a div like this:
<div dojoType="dijit.Tooltip" style="display:none"
connectId="id-of-element-to-connect-the-tooltip-to">
here is my tooltip
</div>
Options for the div:
- position="x" with x = "above", "below", "before" or "after"
- showDelay="x" with x as an integer, how many milliseconds after hover over the element the tooltip should display
- you can modify the look of your tooltip when you use another div inside the tooltip-div and format that div with CSS. Example:
<div dojoType="dijit.Tooltip"
connectId="id-of-element-to-connect-the-tooltip-to">
<div style="width:200px;background-color:red">
here is my tooltip,
200px width and with red background.
</div>
</div>
Use dojox lightbox
The dojox package contains a lightbox to nicely show an photo.
Basic usage: include the dojox.image.Lightbox module in your XPage, set "dojoParseOnLoad" and "dojoTheme" to "true" and add HTML like this:
<a href="bigimage.jpg" dojoType="dojox.image.Lightbox"><img src="smallimage.jpg"></a>
with "bigimage.jpg" as the full sized version of your photo, and "smallimage.jpg" as the thumbnail.
Important: for whatever reason a CSS file is NOT automatically included, so the lightbox will not work as expected. You have to localize the "lightbox.css" and add it to your XPage manually.
Disable default dojo
You can disable the loading of the default Dojo, for example in order to use a more recent version of Dojo.
In the Package Explorer in Domino Designer open your database and find the WebContent/WEB-INF/xp.properties file.
Edit the file and add:
xsp.client.script.libraries=none
More information and links
Here are some useful links for Dojo:
Getting started with Dojo - excellent article on developerworks
Dojo Campus Feature Explorer (does not show everything Dojo has)
Dojo Reference Documentation