Client-Side JavaScript Debugging Tip — Using XSP.dumpObject() and XSP.log()

The XSP object is a client-side JavaScript object that is built and delivered by the XPages runtime and it contains a number of useful functions, some of which are always available and some of which are context-specific. In this post, I’ll show two functions that are useful for client-side JavaScript debugging.

XSP.dumpObject()

The dumpObject() method returns a string representation of all properties of any object that you pass to it. If you want to track down why something isn’t working as expected, it may be helpful to inspect the properties of the object.

The object can be a variable that you programmatically create and modify or it can be an element on the page.

I used to make frequent use of a small script to display all properties of a JavaScript object, but this is a much simpler way to get that information.

Here’s an example of client-side JavaScript to build an object and use XSP.dumpObject() to write out all properties to the browser console:

var myObject = {}
myObject.property1 = 'One';
myObject.property2 = 'Two';
myObject.property3 = 'Three';
myObject.arrayProperty = ['a', 'b', 'c'];

console.log(XSP.dumpObject(myObject));

This information can be very helpful in debugging, so I would recommend using it when handling errors in a try-catch block.

XSP.log()

In addition to logging to the console, you have another similar option available by another XSP function. XSP.log() is analogous to the standard console.log() function that you use when debugging client-side

JavaScript, but the log() method opens up a new browser window and logs messages there, in descending order.

All we have to do is change the last line in the previous snippet:

XSP.log(XSP.dumpObject(myObject));

And this is what we see in a separate browser window:

XSPLog - 1

The log() method will continue appending any messages that you send until you close the window. The next call to XSP.log() will open a new, blank window and start logging again.

Using dumpObject on an HTML field and XPages control

You can also use dumpObject on an HTML element.

For example, if I have a pure HTML select with 3 options and an onchange event, this will be the output of if I get a handle to the element (the id is HTMLComboBox) and dump the object properties:

XSP.log(XSP.dumpObject(dojo.byId('htmlComboBox')));

object
  0: [object HTMLOptionElement] (Maximum Depth Reached)
  1: [object HTMLOptionElement] (Maximum Depth Reached)
  2: [object HTMLOptionElement] (Maximum Depth Reached)
  autofocus: false
  disabled: false
  form: [object HTMLFormElement] (Maximum Depth Reached)
  multiple: false
  name: 
  required: false
  size: 0
  type: select-one
  options: [object HTMLOptionsCollection] (Maximum Depth Reached)
  length: 3
  selectedOptions: [object HTMLCollection] (Maximum Depth Reached)
  selectedIndex: 0
  value: v1
  willValidate: true
  validity: [object ValidityState] (Maximum Depth Reached)
  validationMessage: 
  title: 
  lang: 
  dir: 
  dataset: [object DOMStringMap] (Maximum Depth Reached)
  itemScope: false
  itemType:  (Maximum Depth Reached)
  itemId: 
  itemRef:  (Maximum Depth Reached)
  itemProp:  (Maximum Depth Reached)
  properties: [object HTMLPropertiesCollection]... (Maximum Depth Reached)
  itemValue:  (Maximum Depth Reached)
  hidden: false
  tabIndex: 0
  accessKey: 
  accessKeyLabel: 
  draggable: false
  contentEditable: inherit
  isContentEditable: false
  contextMenu:  (Maximum Depth Reached)
  spellcheck: false
  style: [object CSS2Properties] (Maximum Depth Reached)
  className: 
  oncopy:  (Maximum Depth Reached)
  oncut:  (Maximum Depth Reached)
  onpaste:  (Maximum Depth Reached)
  offsetParent: [object HTMLBodyElement] (Maximum Depth Reached)
  offsetTop: 39
  offsetLeft: 0
  offsetWidth: 67
  offsetHeight: 19
  onabort:  (Maximum Depth Reached)
  onblur:  (Maximum Depth Reached)
  onfocus:  (Maximum Depth Reached)
  oncanplay:  (Maximum Depth Reached)
  oncanplaythrough:  (Maximum Depth Reached)
  onchange:  (Maximum Depth Reached)
  onclick:  (Maximum Depth Reached)
  oncontextmenu:  (Maximum Depth Reached)
  ondblclick:  (Maximum Depth Reached)
  ondrag:  (Maximum Depth Reached)
  ondragend:  (Maximum Depth Reached)
  ondragenter:  (Maximum Depth Reached)
  ondragleave:  (Maximum Depth Reached)
  ondragover:  (Maximum Depth Reached)
  ondragstart:  (Maximum Depth Reached)
  ondrop:  (Maximum Depth Reached)
  ondurationchange:  (Maximum Depth Reached)
  onemptied:  (Maximum Depth Reached)
  onended:  (Maximum Depth Reached)
  oninput:  (Maximum Depth Reached)
  oninvalid:  (Maximum Depth Reached)
  onkeydown:  (Maximum Depth Reached)
  onkeypress:  (Maximum Depth Reached)
  onkeyup:  (Maximum Depth Reached)
  onload:  (Maximum Depth Reached)
  onloadeddata:  (Maximum Depth Reached)
  onloadedmetadata:  (Maximum Depth Reached)
  onloadstart:  (Maximum Depth Reached)
  onmousedown:  (Maximum Depth Reached)
  onmouseenter:  (Maximum Depth Reached)
  onmouseleave:  (Maximum Depth Reached)
  onmousemove:  (Maximum Depth Reached)
  onmouseout:  (Maximum Depth Reached)
  onmouseover:  (Maximum Depth Reached)
  onmouseup:  (Maximum Depth Reached)
  onpause:  (Maximum Depth Reached)
  onplay:  (Maximum Depth Reached)
  onplaying:  (Maximum Depth Reached)
  onprogress:  (Maximum Depth Reached)
  onratechange:  (Maximum Depth Reached)
  onreset:  (Maximum Depth Reached)
  onscroll:  (Maximum Depth Reached)
  onseeked:  (Maximum Depth Reached)
  onseeking:  (Maximum Depth Reached)
  onselect:  (Maximum Depth Reached)
  onshow:  (Maximum Depth Reached)
  onstalled:  (Maximum Depth Reached)
  onsubmit:  (Maximum Depth Reached)
  onsuspend:  (Maximum Depth Reached)
  ontimeupdate:  (Maximum Depth Reached)
  onvolumechange:  (Maximum Depth Reached)
  onwaiting:  (Maximum Depth Reached)
  onmozfullscreenchange:  (Maximum Depth Reached)
  onmozfullscreenerror:  (Maximum Depth Reached)
  onmozpointerlockchange:  (Maximum Depth Reached)
  onmozpointerlockerror:  (Maximum Depth Reached)
  onerror:  (Maximum Depth Reached)
  tagName: SELECT
  id: htmlComboBox
  classList:  (Maximum Depth Reached)
  attributes: [object MozNamedAttrMap] (Maximum Depth Reached)
  onwheel:  (Maximum Depth Reached)
  scrollTop: 0
  scrollLeft: 0
  scrollWidth: 67
  scrollHeight: 19
  clientTop: 0
  clientLeft: 0
  clientWidth: 67
  clientHeight: 19
  scrollTopMax: 0
  scrollLeftMax: 0
  innerHTML: <option value="v1">Value 1</option><option value="v2">Value 2</option><option value="v3">Value 3</option>
  outerHTML: <select id="htmlComboBox"><option value="v1">Value 1</option><option value="v2">Value 2</option><option value="v3">Value 3</option></select>
  previousElementSibling: [object HTMLBRElement] (Maximum Depth Reached)
  nextElementSibling: [object HTMLBRElement] (Maximum Depth Reached)
  children: [object HTMLCollection] (Maximum Depth Reached)
  firstElementChild: [object HTMLOptionElement] (Maximum Depth Reached)
  lastElementChild: [object HTMLOptionElement] (Maximum Depth Reached)
  childElementCount: 3
  nodeType: 1
  nodeName: SELECT
  baseURI: http://127.0.0.2/BlogTesting.nsf/dumpObject.xsp
  ownerDocument: [object HTMLDocument] (Maximum Depth Reached)
  parentNode: [object HTMLFormElement] (Maximum Depth Reached)
  parentElement: [object HTMLFormElement] (Maximum Depth Reached)
  childNodes: [object NodeList] (Maximum Depth Reached)
  firstChild: [object HTMLOptionElement] (Maximum Depth Reached)
  lastChild: [object HTMLOptionElement] (Maximum Depth Reached)
  previousSibling: [object Text] (Maximum Depth Reached)
  nextSibling: [object HTMLBRElement] (Maximum Depth Reached)
  nodeValue:  (Maximum Depth Reached)
  textContent: Value 1Value 2Value 3
  namespaceURI: http://www.w3.org/1999/xhtml
  prefix:  (Maximum Depth Reached)
  localName: select
  ELEMENT_NODE: 1
  ATTRIBUTE_NODE: 2
  TEXT_NODE: 3
  CDATA_SECTION_NODE: 4
  ENTITY_REFERENCE_NODE: 5
  ENTITY_NODE: 6
  PROCESSING_INSTRUCTION_NODE: 7
  COMMENT_NODE: 8
  DOCUMENT_NODE: 9
  DOCUMENT_TYPE_NODE: 10
  DOCUMENT_FRAGMENT_NODE: 11
  NOTATION_NODE: 12
  DOCUMENT_POSITION_DISCONNECTED: 1
  DOCUMENT_POSITION_PRECEDING: 2
  DOCUMENT_POSITION_FOLLOWING: 4
  DOCUMENT_POSITION_CONTAINS: 8
  DOCUMENT_POSITION_CONTAINED_BY: 16
  DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32

If I have a similar Combo Box control in XPages, the output is the same because the HTML element that is generated is virtually identical.

Note: You must pass a fully-qualified client-side ID to dumpObject(), so if you’re passing it an XPages element, use the pass-thru EL syntax "#{id:myControl}" or a client-side query that looks for the element id ending with the name of the control, such as dojo.query('[id~=myControl]')[0].id

console.dir(object)

There’s a method built into browser development tools that performs a similar function. This can be similarly handy when troubleshooting something directly on the page.

For example, to see all of the properties of the first input field on the form, you can use it like this:

console.dir(dojo.query('input')[0]);

Advertisements

Tags:

5 responses to “Client-Side JavaScript Debugging Tip — Using XSP.dumpObject() and XSP.log()”

  1. philriand says :

    Quick comment: to not load unnecessary debug code, the dumpObject() and logw() are actually defined in a different dojo file (xspClientDebug). If you want to use dumpObject() you have to make sure that the module is properly loaded using dojo.require(). Now, the XSP.log() function loads the module synchronously and then delegate to logw(). As you’re using this method, the module is loaded for you so you don’t have to worry about it.

  2. edm00se says :

    To add it to an XPage, you can declare it as a resource Dojo Module of “ibm.xsp.widget.layout.xspClientDebug” or programmatically via dojo.require(“ibm.xsp.widget.layout.xspClientDebug”) from either a script block or directly from the JS console.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: