Help system

53 views
Skip to first unread message

Phil Petree

unread,
May 30, 2013, 11:30:33 AM5/30/13
to prototype-s...@googlegroups.com
Has anyone developed an inline help system?  Am I barking up the wrong tree or is there an easier way to do this?
 
Ideally we could just drop the div in anywhere we wanted, the help icon would always float to the right of the label/input and when the user clicked the help icon we'd get a context sensitive help solution.
 
I was thinking of something that could be built off a div like this:
 
prototype:
document.observe("dom:loaded", function() {
    $$('div.help').each(function(item) {
        item.observe('onclick', function() {
               // get items id
               // use ajax call to get help info from server
               // populate div
               // apply pop-up class
               // set handler to process dismiss click () {
                   // delete context help
                   // restore help class
               };
           });
    });
});
 
html:
<div class='help' id='topic'></div>
 
css:
.help {?}
.popup-help {?}
.icon-help {background: #fff url(images/icons/help_32x32.png) top left no-repeat;}

Walter Lee Davis

unread,
May 30, 2013, 11:41:11 AM5/30/13
to prototype-s...@googlegroups.com
This would be pretty easy to do. Prototype gives you lots of tools to make this possible, the bulk of this effort would probably go into the CSS to style your tooltips.

On May 30, 2013, at 11:30 AM, Phil Petree wrote:

> Has anyone developed an inline help system? Am I barking up the wrong tree or is there an easier way to do this?
>
> Ideally we could just drop the div in anywhere we wanted, the help icon would always float to the right of the label/input and when the user clicked the help icon we'd get a context sensitive help solution.
>
> I was thinking of something that could be built off a div like this:
>
> prototype:
> document.observe("dom:loaded", function() {
> $$('div.help').each(function(item) {
> item.observe('onclick', function() {

This would be item.observe('click' ... you never use the 'on' part in Element/Event.observe.

> // get items id

item.id or item.readAttribute('id')

> // use ajax call to get help info from server
> // populate div
> // apply pop-up class

new Ajax.Updater('theDivId', '/url/to/help/system', {
parameters: {id: theIdYouGotAbove},
onSuccess: function(){
item.addClassName('tooltip');
}
});

> // set handler to process dismiss click () {
> // delete context help
> // restore help class
> };

document.on('click', 'div.tooltip', function(evt, elm){
elm.update().removeClassName('tooltip');
});


The "on" handler is really helpful, it can manage elements that weren't in place when the page loaded. One handler to rule them all, not a separate handler per tooltip.

> });
> });
> });
>
> html:
> <div class='help' id='topic'></div>
>
> css:
> .help {?}
> .popup-help {?}
> .icon-help {background: #fff url(images/icons/help_32x32.png) top left no-repeat;}

Hope this helps,

Walter

Phil Petree

unread,
May 30, 2013, 2:24:21 PM5/30/13
to prototype-s...@googlegroups.com
Certainly seems like it should be easy... I guess that's why I was kinda surprised to not see where anyone else had put one together... certainly was nothing on scripteka... could add some serious value to some sites.
 
I'll play around with it on Sunday and see what I can cobble together... of course it looks like you did most of the work in 5 minutes and I'll spend most of the day playing around with it! LOL
 
I'll post what I come up with...


 

--
You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group.
To unsubscribe from this group and stop receiving emails from it, send an email to prototype-scripta...@googlegroups.com.
To post to this group, send email to prototype-s...@googlegroups.com.
Visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.



Walter Lee Davis

unread,
May 30, 2013, 6:28:47 PM5/30/13
to prototype-s...@googlegroups.com
I think you could make the whole thing pretty simply. Rather than creating a separate handler (with each()) for each .help element, you could wrap the entire thing in one "on" handler, which you would not need to customize per page or worry about dom:loaded or anything:

document.on('click', '.help', function(evt, elm){
var tip = elm.down('div');
new Ajax.Updater(tip, 'path/to/help', {
parameters: {id: elm.id},
onCreate: function(){
tip.addClassName('loading');
},
onSuccess: function(){
tip.removeClassName('loading');
tip.addClassName('tooltip');
}
});
});

document.on('click', '.tooltip', function(evt, elm){
evt.stop();
elm.update().removeClassName('tooltip');
});

That's expecting a structure like this:

<div class="help" id="widget_1"><div></div></div>

You could use some other construction if you like, but that would do the trick. The rest will be creating the CSS for the tooltip, and the Web service to fill it in.

If you didn't want to get the Ajax thing going, you could also just put the tooltip in the help element itself, maybe in a data-attribute. That depends on how much content there would be. It would be completely instantaneous.

Walter

Jason Westbrook

unread,
May 30, 2013, 7:05:34 PM5/30/13
to prototype-s...@googlegroups.com
If you want to use tooltips or popovers you could use the PrototypeJS Twitter BootStrap tooltips or popovers


Jason Westbrook | T: 313-799-3770 | jwest...@gmail.com


Phil Petree

unread,
May 31, 2013, 8:42:23 AM5/31/13
to prototype-s...@googlegroups.com
My reason for using ajax is three fold:
  1. To do a real context sensitive help system would require more help text than would be feasible to integrate for each control, dictionary definition or decision point on each page.
  2. By including just the <div> we minimize the number of bytes transferred thereby reducing bandwidth requirements and improve page load times. Why transfer data on help points when those may never be accessed or accessed only once?
  3. The help system could include short videos (we're using camstudio to capture desktop mouse moves and voice over).

Phil Petree

unread,
Jun 9, 2013, 2:03:35 PM6/9/13
to prototype-s...@googlegroups.com
Here's what I've come up with on the context sensitive help system (thanks to a few tips from Walter). I'm not crazy about the idea of having to include the hidden modalWindow on each page that uses the help but I found it much simpler than doing it all inline (maybe that's just my lacko skill set showing <g>):
 
sample html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1250">
<title>Context Sensitive Help</title>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js"></script>
<script type='text/JavaScript' src='help.js'></script>
<link rel='stylesheet' type='text/css' href='help.css' />
</head>
<body>
  <!-- this div is used by the context help system -->
  <div id="modalWindow" class="modalHelpWindow" style="display:none;">
    <div class='help_title'>Help<div class='help_close'></div></div>
    <div id='help' class='help_content'></div>
  </div>
  <div class='content'>
    <form>
      <label for='name'>Name:<div class="help" id="name"></div></label>
      <input type='text' name='name' /><br>
      <label for='occupation'>Occupation:</label>
      <input type='text' name='occupation'/><div class="help" id="occupation"></div><br>
      <label for='sex'>Sex:<div class="help" id="sex"></div></label>
      <input type='radio' name='sex' value='female' /> Female&nbsp;&nbsp;<input type='radio' name='sex' value='male' /> Male
    </form>
  </div>
</body>
</html>
help.css:
/* CSS Document */
div.modalHelpWindow
{
 position: absolute;
 top: 50%;
 left: 50%;
 width:400px;
 height:250px;
 padding-top: 0px;
 margin-top: -125px;   /*set to a negative number 1/2 of your height*/
 margin-left: -200px; /*set to a negative number 1/2 of your width*/
 border: 4px solid green;
 background-color: #ffffff;
  z-index: 100;
}
.help_title
{
  /* help system title bar */
  float: left;
  top: 0px;
 width:400px;       /* same width as the help popup */
 height:25px;       /* this plus height of help_content = height of popup */
  background: lightgray;
  Padding: 5px;
  overflow: hidden;
}
.help_close
{
  /* the 'x' to close the help dialog */
  position: absolute;
  height: 16px;       /* has to have a height/width or it won't display */
  width: 16px;
  margin-left: 345px; /* how far from left to position the 'x' */
  background: url(images/delete_16x16.png) top no-repeat;
}
.help_content
{
 width:400px;
 height:225px;
  overflow:auto;
  background:#fff;
}
.help
{
  display: inline;
  height: 16px;
  width: 16px;
  margin-left: 3px;
  padding-right: 20px;
  background: url(images/help_16x16.png) left no-repeat;
}
help.js:
// JavaScript for context help system

document.on('click', '.help', function(evt, elm){
  new Ajax.Updater('help', 'server/help.php', {
    method: 'post',
    parameters: {id: elm.id},
    onSuccess: function(){
      openHelpWindow();
    }
  });
});
document.on('click', '.help_close', function(evt, elm){
  evt.stop();
  closeHelpWindow()
});
// I implemented these as functions
// for easy customization
function openHelpWindow()
{
  $('modalWindow').show();
}
// close the modal window
function closeHelpWindow()
{
  $('modalWindow').hide();
}
server/help.php:
<?php
echo "<center><h3>User requested help on:</h3><h1>" .$_POST['id'] ."</h1></center>";
?>
The MySQL table I implemented:
CREATE TABLE IF NOT EXISTS `help` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `language` char(2) CHARACTER SET ascii NOT NULL COMMENT 'language of this record',
  `help_topic` char(20) CHARACTER SET ascii NOT NULL COMMENT 'help topic',
  `help_content` text CHARACTER SET ascii NOT NULL COMMENT 'help content',
  PRIMARY KEY (`id`),
  FULLTEXT KEY `help_system` (`help_topic`, `help_content`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='context help table' AUTO_INCREMENT=1;
INSERT INTO `help` (`id`, `language`, `help_topic`, `help_content`) VALUES
(1, 'EN', 'name', 'Help about the name field goes here...');

Monty Munro

unread,
Jun 9, 2013, 3:05:01 PM6/9/13
to prototype-s...@googlegroups.com
To get around the idea of having the embedded modalWindow in your html, you could build it and inject it on dom:loaded

document.observe('dom:loaded', function () {
  var helpShell = String()
    +  "<div class='help_title'>Help<div class='help_close'></div></div>"
    +  "<div id='help' class='help_content'></div>";

  var mhw  = new Element( 'div', { id : 'modalWindow', 'class' : 'modalHelpWindow', style : 'display:none;' }).insert(helpShell);

  $(document.body).insert( mhw);
});

might want to inline all of the css on the shell div parts.

Phil Petree

unread,
Jun 9, 2013, 3:17:14 PM6/9/13
to prototype-s...@googlegroups.com
Inserting has it's merits in that the centering method I used will not work if you have scrolled way down via the scroll bars so inserting the modalWindow will keep the help popup "near" the element from which the help was invoked... on the flip side, I've had issues with inserting new elements and inherited CSS as attributes not explicitly set are inherited from the parent.

Reply all
Reply to author
Forward
0 new messages