.. File nm/guidance/_base.js This is a comment in the documentation, which is in reStructured text. The official documentation starts here, with the title: ========== guidance ========== :Author: Jaap Murre :Version: 0.1 :Date: November, 2012 **************** Reference Manual **************** Introduction ------------ This is a JavaScript library that adds on-page guidance to a web page. After starting a 'tour', a series of tooltip dialogs highlights the interesting or to-be-learned parts of a page. Arbitrary HTML ++++++++++++++ The contents of the tooltip dialogs (i.e., the actual guidance texts) are provided in each element in a special attribute: `data-guidance`. For example: `
...
`. Arbitrary HTML may be used including images. Use `title` attribute as guidance text ++++++++++++++++++++++++++++++++++++++ In case a help text is an empty string, the contents of the title attribute will be used automatically. This may be handy in case you want the title tooltip to have a double role. Note that the HTML tags will then appear unparsed in the non-guidance tooltips in the browser. Hidden elements are skipped +++++++++++++++++++++++++++ If elements are hidden with `display: none`, they will not occur in a guidance tour. Starting, stopping and resuming tours +++++++++++++++++++++++++++++++++++++ Call `start()` to start a tour. Tours may be stopped and then either started from the beginning by calling `stop()` or resumed from the last position by calling `continue()`. Executing code on visit enter and leave +++++++++++++++++++++++++++++++++++++++ It is possible to execute certain code when a guider enters a node and when it leaves again, using the `data-guidance-onenter` and `data-guidance-onleave' attributes, as follows:: data-guidance-onenter="dijit.byId('titlepane1')._setOpenAttr(true);" data-guidance-onleave="dijit.byId('titlepane1')._setOpenAttr(false);" This would open a title panel on entering (i.e., showing the guide on a title pane node), closing it again on leaving. Changing the visiting order +++++++++++++++++++++++++++ It is also possible to change the display order by providing the `data-guidance-position` attribute with a position, e.g.:: data-guidance-position="5" Ordering is not absolute but relative, with nodes without `data-guidance-position` attributes appearing before those with an attribute (in on-page order). It is also possible, therefore, to use strings to specify an order. Changing styles +++++++++++++++ It is possible to change the style of the highlighting of elements by specifying something like:: data-guidance-style="border: 1px solid #aa0; background-color:#c8ffff;" After this element has been visited in the tour, that style will be maintained (also when moving to Previous). Similarly, you can change the background color (only) of the tooltip dialog as follows:: data-guidance-bgcolor="#c8ffff" Again, the color will be maintained after this. Note, that the help texts themselves can contain arbitrary HTML, including styled elements. Multiple tours on a single page +++++++++++++++++++++++++++++++ It is possible to define multiple tours on a single page and have the start with different buttons. To move an element into a separate tour (and remove it from the default tour), use:: data-guidance-tour="tour2" You can use any identifying string here. Each element can be in only one tour. Start the tour with `start("tour2")`. Calling `continue()` will always resume the last tour. The default tour (i.e., without `data-guidance-tour` attribute) is started by calling `start()` without arguments. Usage ----- Installation and set-up +++++++++++++++++++++++ We assume that the the ``nm`` directory, with the file ``keymapper.js`` underneath it, resides itself at the same level as the dojoroot:: dojoroot/ dojo/ dojox/ nm/ guidance.js guidance/_base.js docs/ tests/ Register the ``nm`` module and require ``guidance`` as follows:: dojo.registerModulePath("nm","../../nm"); // path is relative to dojo.js file dojo.require("nm.guidance"); It is necessary to include the proper style sheets for the chosen theme. E.g., in case of claro:: Be sure to also add the style class to the body:: Usage by end-user (keyboard short-cuts) +++++++++++++++++++++++++++++++++++++++ The Next button of the tooltip dialogs is focussed, meaning that the user can move to the next guidance text by pressing the Space bar or Esc button. With Tab, the user can move to the Previous and then Stop buttons. Shift-Tab moves in the other direction. Note, that the element that is visited next in the tour will scroll into view when necessary. Example of use ++++++++++++++ The following code illustrates some of the options above. A more complete example can be found in the tests directory:: Test On-page Guidance
 





Click arrow to close me.
This pane opens when a guiders enters (i.e., is activated on this node) and should close when clicking Next.
Right now, the guide is tied tot the bar and not the content, so it appears in the wrong spot.

On-page Guidance

This page has on-page guidance based on the Dojo Toolkit. Each element that requires guidance is given an extra attribute data-guidance="My guidance test.. On page load the init_guidance().start() is called and it works. Or start tour later by calling start() later.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Paragraph 2, which is the second paragraph. Here, the style of the highlighted element changes to light blue.

Paragraph 1, which is actually the third paragraph.

This is a hidden paragraph, number 5, but not shown.

Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.

Future improvements +++++++++++++++++++ - Disable Previous button on position 0 and Next button on end. - Add attribute to over-ride where the tooltip will appear (e.g., `data-guidance-location='top'`) .. The actual code follows below. Notice that it is indented so that it is considered one long comment by restructured text. */ dojo.provide("nm.guidance"); dojo.require("dijit.TooltipDialog"); dojo.require("dijit.form.button"); dojo.require("dojo.window"); dojo.require("dojox.html.styles"); // Allows creation of dynamic styles, e.g., a new class nm.guidance = function() { var global_highlight_style = "border: 1px solid #aa0; background-color:#ffffc8;", current_highlight_style = global_highlight_style; // Using this, we don't need to use an external style sheet dojox.html.styles.insertCssRule(".highlight_guided_node",global_highlight_style); var nodes = [], i, allnodes = dojo.query("[data-guidance]").filter(function(node){ return dojo.style(node,'display') != 'none'; }), position = 0, prev_button_string = "", stop_button_string = "", next_button_string = ""; // Sort nodes, such that nodes without a data-guidance-position attribute come first, in order of appearance // and are then followed with those that do have such an attribute, in the order specified. // The next three lines are necessary to stablize the sort. for (i = 0; i < allnodes.length; i++) { allnodes[i].index = i; } allnodes = allnodes.sort(function(node_a,node_b){ var a = dojo.attr(node_a,'data-guidance-position'), b = dojo.attr(node_b,'data-guidance-position'); if (a === b) { return node_a.index > node_b.index ? 1 : -1; } else { return a > b ? 1 : (a < b ? -1 : 0); } }); var guider = new dijit.TooltipDialog({ title:"On-page Guidance Tour", parseOnLoad: true, content: "On-page guidance is not available for this page" }); dojo.style(guider.domNode.children[0],"background-color","#ffffc8"); guider.move_to = function(pos) { var node = nodes[pos], onguide = "", onstyle = global_highlight_style, onbgcolor = ""; if (node) { onstyle = dojo.attr(node,"data-guidance-style"); if (onstyle) { dojox.html.styles.removeCssRule(".highlight_guided_node",current_highlight_style); dojox.html.styles.insertCssRule(".highlight_guided_node",onstyle); current_highlight_style = onstyle; } onbgcolor = dojo.attr(node,"data-guidance-bgcolor"); if (onbgcolor) { dojo.style(guider.domNode.children[0],"background-color",onbgcolor); } dojo.addClass(nodes[pos],"highlight_guided_node"); dojo.window.scrollIntoView(node); onguide = dojo.attr(node,"data-guidance-onenter"); if (onguide) { eval(onguide); // TODO: This is probably dangerous!!! } // Use title (=tooltip) attribute content if data-guidance is (deliberately) left empty guider.set('content',"
" + (dojo.attr(node,"data-guidance")||dojo.attr(node,"title")) + "

" + prev_button_string + stop_button_string + next_button_string) + "
"; dijit.popup.open({ popup: guider, around: node }); dojo.byId('guider_next_button').focus(); } else { if (position > 0) { alert("You completed the tour!"); } this.stop(); } } guider._clearCurrentStyle = function() { if (nodes[position]) { dojo.removeClass(nodes[position],"highlight_guided_node"); } } guider._onleave = function() { guider._clearCurrentStyle(); if (nodes[position]) { eval(dojo.attr(nodes[position],"data-guidance-onleave")||""); } } guider.start = function(tour) { if (tour) { nodes = allnodes.filter(function(node) { return dojo.attr(node,'data-guidance-tour') === tour; }); } else { nodes = allnodes.filter(function(node) { return dojo.attr(node,'data-guidance-tour') === null; }); } position = 0; guider.move_to(position); } guider["continue"] = function() // continue is a reserved word in JavaScript { guider.move_to(position); } guider.stop = function() { guider._onleave(); dijit.popup.close(this); } guider.previous = function() { guider._onleave(); guider.move_to(--position); } guider.next = function() { guider._onleave(); guider.move_to(++position); } return guider; };