I recently needed a way to communicate with the users of a web page via a somewhat "interactive" manner, without using Flash or Java. Alert boxes were
simply too obtrusive. I thought about MS Agent, but then it would only be compatible with IE. So I decided to build my own that would, in part, mimic the functionality
of MS Agent, but be as cross-browser as possible.
Using the Code
The class itself is pretty easy to use. You supply your own image and small adjustments to make sure everything goes where you want to.
window.onload = function()
var monkey =
myCritter = new JCritter(monkey);
You can also use jcritter-mini.js or jcritter-micro.js. jcritter-mini.js is a minimized version with comments and white spaces removed.
jcritter-micro.js is an extremely compact version and the code is obfuscated slightly. jcritter-mini.js and jcritter-micro.js are about half
to one third the size of the original jcritter.js.
You shouldn't set any of these. They are included so you can test the current state of your critter.
JCritter.version: Display JCritter version.
JCritter.isHidden: Boolean value. Shows current display state of the critter.
JCritter.isSpeaking: Boolean value. Shows current speaking state of the critter.
JCritter.drawAgent(): Draws the agent on the screen. Shouldn't need to use it.
JCritter.drawBalloon(): Draws the balloon on the screen. Shouldn't need to use it.
JCritter.draw(): Draws both the balloon and critter. Use it after creation or to realign your critter.
JCritter.say(text, alignment): Shows the balloon and says the desired text.
alignment is optional and can be any
valid CSS '
text-alignment' value. If
say is called with no arguments, the contents of the balloon are returned.
.hush(): Removes the balloon.
.show(): Shows the critter.
.hide(): Hides the critter and balloon.
.mute(): Mutes the critter. The critter will ignore the
say method until
unMute is called.
.unMute(): Unmutes the critter
destroy(): Destroys the critter object. You'll probably want to call this on your body's
.play(animationName): Switches the current image to the image specified by the animation name. Used with animated GIFs,
you can provide your own ad-hoc animations.
.setFontSize(size): Sets the font size.
.setFontColor(color): Sets the font color.
.setAgent(agent): Sets the current agent to
object.eventname = function()
.onClick: Called when the critter is clicked.
.onMouseIn: Called when the mouse enters the critter's boundaries.
.onMouseOut: Called when the mouse moves outside the critter boundaries.
It's possible to add your own custom critter images, rather than using the default image that comes with the script. Since it's impossible to determine
the exact placement of the speech bubble outside the square boundary of the image itself, several options have been provided to allow you to "fine tune"
and pass it to the
var penguin =
width: The width of your critter.
height: The height of your critter.
src: The image source of your critter.
adjustTop: Adjustment of your critter from the top of the viewing area.
adjustLeft: Adjustment of your critter from the left of the viewing area.
speechTop: Adjustment of your balloon from the top of your critter.
speechLeft: Adjustment of your balloon from the left of your critter.
animations: An object containing a list of animation names and an image to coincide with the animations.
"ends". Because of this, you will want to be careful using looping animations, and your animations should return to the default image you want to display when your critter is idle.
The first thing we must do is create our
DIVs that will hold the elements we work with. We will be using five
DIVs. The first
DIV will contain
DIVs 2-4. It will hold the bubble image and a
DIV for the text image. The last
will contain the image of the agent or critter that will be speaking.
The two "main" DIVs are outlined in black
The three DIVs that make up the bubble DIV
The actual bubble DIV
As you can see, the bubble image is much large than what we need. This is to accommodate large amounts of text. In order to accomplish this, we use a technique
called "sliding doors". Using CSS, we will set the background image of the red and green
DIV to the top and bottom of the bubble image, respectively.
bubbleTop.style.background = 'url(bubble.gif) no-repeat top';
bubbleTop.style.padding = '25px 8px 0px';
bubbleBottom.style.background = 'url(bubble.gif) no-repeat bottom';
bubbleBottom.style.padding = '35px 8px 0px';
You'll notice the bubble is now complete, but there is no text. We need to have a
DIV between the top and bottom with a bit of padding on the left and right.
bubbleText.style.paddingLeft = '10px';
bubbleText.style.paddingRight = '10px';
Now the only real issue left is positioning. The critter/agent needs to be placed in the bottom left corner of the view port. Unfortunately, there is no built-in mechanism
to get the view port of a browser window, so after searching the web a bit, I managed to find some code that will identify this allusive property.
window.innerWidth || (document.documentElement.clientWidth || (document.body.clientWidth || 0));
window.innerHeight || (document.documentElement.clientHeight || (document.body.clientHeight || 0));
If all of our checks fail, we'll return an x and y of 0. This isn't ideal, but it's better than returning nothing, which will certainly break the script.
Now that we know the width and height of our view port, we can subtract the width and height of our critter/agent. This will allow us to place it in the corner
of the screen. We have to add a few cosmetic pixels here or there to position it as desired. Once the critter/agent is in place, the word balloon can be positioned.
The default positioning is relative to the top left corner of the
DIV that contains the critter/agent. Since it's impossible to automatically know what our image
looks like (where the mouth is, etc.), we adjust our balloon using the
speechTop options specified when we created our agent.
Once everything is positioned, we just need to set the properties of our two "master"
DIVs to hidden/visible whenever we need
to show/hide the critter/agent or the speech balloon.
- Internet Explorer 7
- Internet Explorer 6
- Positioning can get screwed up when using targets. You have to use
draw to fix or scroll/resize the page (forces a redraw).
Points of Interest
This code works best on "Web 2.0" sites, where pages are not forced to refresh as often. IE6 doesn't support the
fixed property. As a result,
whenever the script detects that the user is using the IE6 browser, it will change the position to
absolute, and add the
window.onscroll callback. If you resize your window, you will need to call the
draw() method again to realign your critter.
- Wednesday, October 22, 2008: Updated article. Updated zip file with minimized versions. Random bug fixes.
- Friday, September 5, 2008: Updated article.
- Tuesday, June 10 2008: Updated article.
- Monday, April 28 2008 : Updated article.
- Wednesday, March 5 2008: Restored article (what the heck?).
- Tuesday, October 23 2007: Restored article (deleted accidentally).
- Tuesday, October 17 2007: Uploaded Version 0.5.
- Animation support added.
- Removed event handlers on
- Tuesday, October 16 2007: Uploaded Version 0.4.