Tuesday, December 21, 2010


Keycaster is a jQuery plugin was written to add a keystroke and mouse visualizer to your browser window. It is similar to keycastr for the mac, except this only works inside the browser window.

This plugin is still in the alpha stage because it doesn't show all shifted keys properly and some key symbols do not work in all browsers (written mainly to work in Firefox). Also I plan on making this script work as a bookmarklet so you can just click on a link to activate it.

Update: You can now add this script to any page using this bookmarklet - Keycaster - just drag it into your browser bookmarks and click on it whenever you need to visualize your mouse or keyboard actions.

Sunday, November 28, 2010

jQuery UI Keyboard Widget

If you need support, please contact me here:

I found this widget by Jeremy Satterfield which adds an virtual keyboard to any input or text area. I really liked it and had a lot of ideas that I wanted to add :P

So, I made a github repository, added a few of my ideas to the widget so now I present to you updated keyboard widget! (more updates to come!)

Here are some of the changes I made to version 1.5:
  • Changed class of preview window from 'ui-state-active' to 'ui-widget-content' because it looks bad in some themes.
  • Added 'ui-widget-content' class to the element (input or textarea).
  • Added International keyboard Layout (AltGr key) and expanded the keysets up to four.
  • Added more special/"action" keys:
    • Previous text only keys now have a companion symbol only key. The abbreviated names contain only a symbol so as to fit the layout style as desired.
    • Added alt key to allow accessing two additional key sets.
    • Changed name of {neg} to {sign}. This key changes the sign of the input.
    • Added tab key
  • Fixed positioning utility problem I added in the last version - show the popup before positioning (duh).
  • Added position option to allow positioning the keyboard anywhere around the input/textarea.
  • Added display option to support multiple languages or change key symbols.
  • Added actionClass option to allow changing the style of the accept and cancel keys.
  • Added lockInput option to lock or unlock the ability to access the preview window.
  • Added keyBinding option to change the keyboard key behaviour.
  • Added useCombos to enable the dead key emulation which allows entering diacritic key combinations.
  • Using the escape key now closes the keyboard.
  • Added mousewheel support to allow scrolling through the other keysets while hovering over a key.
  • Added ARIA support (may not be complete).
And on my to do list are:
  • Allow inserting text at the caret inside the preview window.
  • Add max length setting.
  • Add additional buttons to change key sets (similar to the alt key).
  • Add callbacks.
  • Add _destroy function.
  • Work on setting up one keyboard per layout to speed up initialization.

Wednesday, November 17, 2010


There is a very cool sliding accordion on Apple's Store site to compare various computers (click compare then scroll).

SqueezeBox is a jQuery plugin written to emulate that effect. It was designed to use the same themes available for jQuery UI, or you can add your own theme.

Click on the image or go to the demo page.

  • Easily change the theme but just loading in a different jQuery UI theme (Redmond theme shown).
  • SqueezeBox works with both collapsible and non-collapsible blocks.
  • Activate a header numerous ways:

    1. Use browser hash marks to target the header ID - used on initial page load.
    2. Click on any header to make it active - all headers above it will collapse using a smooth animation.
    3. Use the script to set the active header.
Download it from my github repository.

Monday, November 8, 2010

Kwicks for jQuery v2.0

I was recently was inspired to work on Kwicks for jQuery v1.5.1 by Jeremy Martin because it hasn't been updated for a few years. So, I ended up changing the plugin structure to make it easier (for me) to add a getter, setter, event hooks and custom events.

Check out the demo. Hopefully there is enough documentation to make adding a kwick to your own site easy! Download Kwicks for jQuery 2.0 here.

Wednesday, October 20, 2010

Web Search Widget

I started messing around with the jQuery UI widget factory and put together a widget that allows you to easily add a web search button to your site (no server side scripting required).

There isn't much for me to write here since I put almost all of the needed instructions on the WebSearch github page. I hope someone finds it useful!

Tuesday, September 28, 2010


I've been working on improving the AnythingSlider jQuery plugin by Chris Coyier of CSS-Tricks.com. The project was moved to github, so you can always get the latest version there... My version is up to 1.4 and you can check out a demo of it here - try starting both YouTube videos, then start the slideshow (doesn't work in Internet Explorer properly).

Features include:
  • Panels are HTML Content (can be anything).
  • Multiple AnythingSliders allowable per-page.
  • Infinite/Continuous sliding (always slides in the direction you are going, even at "last" slide).
  • Optionally resize each panel (specified per panel in css).
  • Optional Next / Previous Panel Arrows.
  • Use keyboard navigation or tabs that are built and added dynamically (any number of panels).
  • Link to specific slides or go forward or back one slide from static text links
  • Each panel has a hashtag (can link directly to specific panels).
  • Optional custom function for formatting navigation text.
  • Auto-playing slideshow (optional feature, can start playing or stopped)
  • Pauses playing YouTube videos when not in view and resumes them when in view (only in non-IE browsers & if files are hosted on the web).
  • If slideshow is active, a playing video will complete before the slideshow continues.
  • Pauses slideshow on hover (optional).
  • Optionally play the slideshow once through, stopping on the last page.

Thursday, September 16, 2010

Switched file hosting sites

Apparently all the files hosted on myotherdrive.com are no longer available for direct linking. So I moved the important files over to dropbox.com and updated the appropriate posts.

Sorry if there was any inconvenience for anyone.

Wednesday, August 25, 2010

World of Warcraft Loot Systems

I've added scripts that parse lua files from EPGP, Ni Karma and Suicide Kings addon loot systems. These scripts were written for websites that can't use php or other server side systems.

Click the link below to go to the github page, then click on the "Download Source" button.
Follow the examples provided.

Tuesday, August 24, 2010

Tooltips - Jatt (Just another tooltip)

This is an updated version of my other tooltip script. With this version, you can:
  • Dynamically modify the tooltip using metadata.
  • Set a tooltip direction (8 directions: n, ne, e, se, s, sw, w & nw).
  • Tooltip content can be obtained from a selected object attribute, a different object on the same page, or via ajax.
  • Ajax calls can include jquery selectors to target specific page content.
  • Removed support for the dhtmltooltip script (the code is there, but commented out).
Adding the Tooltips
First make sure you have jQuery installed on your site, download the latest version from jQuery. Then add the following CSS and script to your site, or you can download the script here.

Basic setup
<style type="text/css">
.tooltip, .preview, .screenshot { cursor:pointer; }
#tooltip { width: 250px; }
#tooltip, #preview {
 border: 1px solid #333333;
 opacity: 0.9;
 filter: alpha(opacity=90);
 border-radius: 1em;
 -moz-border-radius: 1em;
 -webkit-border-radius: 1em;
<script src="jatt.js" type="text/javascript"></script>
<script type="text/javascript">
Using the Tooltips
  • Basic Tooltip

    basic tip (a)<a class="tooltip { direction: n; width: 100px; background: #222; color: #ddd; }" href="#" title="Tooltip (a) Content">basic tip (a))</a>
    External page (a)<a class="tooltip { direction: ne; width: 200px; }" href="http://wowmotty.blogspot.com/2009/06/new-and-improved-jquery-tooltips.html #Blog1_cmt-3390748906554490641">External page (a)</span>
    Object on page (div)
    <div class="tooltip { direction: e; width: 150px; background: #9bff8f; color: #333; }" rel="#tip1">Object on page (div)</div>
    <div id="tip1" style="display:none">Hi</div>
    <img class="tooltip { direction: se; width: 200px; background: #808080; color: #000; opacity: 1; }" src="http://i201.photobucket.com/albums/aa236/Mottie1/testsite/icons/hideshow.gif" title="Tooltip (img) Content" >
    Link (span)<span class="tooltip { followMouse: false; direction: s; width: 300px; background: #008080; color: #ddd; }" title="Tooltip (span) Content">Link (span)</span>
    • class="tooltip" (required) - This class activates the tooltip
    • class="tooltip { metadata }" (optional) - Add any of the predefined options (listed below) or any css style to apply to the tooltip.
    • title="Tooltip content" (optional) - The title attribute should contain whatever you want to display inside the tooltip. This can include HTML but Do NOT use quotes in the content. If you are using HTML tags, replace the quotes with single quotes, e.g. <img src='hideshow.gif'>. If you must use quotes to surround some text, use the HTML escape code &quot; - this text has &quot;quotes&quot; around it.
    • rel="selector" (optional) - If the "title" attribute is empty, the script will look in the "rel" attribute for a selector that points to an object containing the tooltip content (see the "External object (div)" example above).
    • href="page.htm #target span:first" (optional) - If the "title" and "rel" attributes are both empty, the script will look in the "href" attribute for a URL to an external page. The URL can be followed by an id or class selectors pointing to the tooltip contents (see the "External page (a)" example above).
  • Preview Tooltips

    <a class="preview { direction: e; opacity: 1; text-align: center; }" href="URL to full size image" title="Google's Logo"><img src="URL to image thumbnail"></a>
    • class="preview" (required) - This class activates the tooltip which puts the linked image (from the href) into a tooltip. The tooltip size is adjusted automatically to fit the image.
    • class="preview { metadata }" (optional) - Add any of the predefined options (listed below) or any css style to apply to the tooltip.
    • href="URL to full size image" (required) - URL to the image, for previewing in the tooltip and the URL you go to when you click on the image.
    • title="TOOLTIP CONTENT" (optional) - This content becomes the image caption located below the image inside the tooltip. Note: Do NOT use quotes in the content. If you are using HTML tags, replace the quotes with single quotes, e.g. <img src='http://i201.photobucket.com/albums/aa236/Mottie1/testsite/icons/Nax2-10.gif'>. If you must use quotes to surround some text, use the HTML escape code &quot; - this text has &quot;quotes&quot; around it.
    • <img src="URL to image thumbnail"> (required) - This will be the thumbnail of the URL image (in orange), or you can pick any image as I did here. Or you can replace the <img> with text.
  • Screenshot Tooltips

    LMYC<a class="screenshot { direction: e; opacity: 1; text-align: center; } " href="http://www.guildportal.com/Guild.aspx?GuildID=194525&TabID=1643295" title="<center>Loch Modan Yacht Club</center>" rel="http://www.axiomfiles.com/Images/Spotlight/194525.jpg">LMYC</a>
    Google<a class="screenshot { direction: e; }" href="http://www.google.com" title="<center>Google</center>" rel="#">Google</a>
    • class="screenshot" (required) - This class activates the tooltip that gets the site screenshot image from the rel attribute (in light blue)
    • href="URL" (required) - URL of the target website
    • title="Tooltip content" (optional) - This content becomes the screenshot (image) caption inside the tooltip. Note: Do NOT use quotes in the content. If you are using HTML tags, replace the quotes with single quotes, e.g. <img src='http://i201.photobucket.com/albums/aa236/Mottie1/testsite/icons/Nax2-10.gif'>. If you must use quotes to surround some text, use the HTML escape code &quot; - this text has &quot;quotes&quot; around it.
    • rel="Website_Screenshot.jpg" or rel="#" (required) This attribute can contain either the URL to the screenshot image of the site to which you have the link pointing. Yes, you will have to take, resize and upload the screenshot image yourself OR you can now use rel="#" to have Websnapr.com generate a thumbnail of the site for you.
    • text or image (required) - Text or image that becomes the clickable link to the site.
  • Initializing the script (showing all default settings)

      // options that can be modified by metadata
      direction      : 'n',     // direction of tooltip
      followMouse    : true,    // tooltip follows mouse movement
      content        : 'title', // attribute containing tooltip text
      speed          : 300,     // tooltip fadein speed
      local          : false,   // if true, the script attachs the tooltip locally; if false, the tooltip is added to the body
      xOffset        : 20,      // x distance from mouse (no negative values)
      yOffset        : 20,      // y distance from mouse (no negative values)
      zIndex         : 1000,    // z-index of tooltip
      // options not supported by metadata
      live           : false,                 // use live event support?
      metadata       : 'class',               // attribute that contains the metadata, use "false" (no quotes) to disable the metadata.
      activate       : 'mouseenter focusin',  // how tooltip is activated
      deactivate     : 'mouseleave focusout', // how tooltip is deactivated
      // change tooltip, screenshot and preview class
      tooltip        : '.tooltip',             // tooltip class
      screenshot     : 'a.screenshot',        // screenshot class
      preview        : 'a.preview',           // preview class
      // tooltip & preview ID (div that contains the tooltip)
      tooltipId      : 'tooltip',             // ID of actual tooltip
      previewId      : 'preview'              // ID of screenshot/preview tooltip 
  • List of Options

    KeyValue (default shown)Description
    direction'n'Choose the direction of the tooltip (in quotes; choose from n, ne, e, se, s, sw, w, nw).
    followMousetrueWhen hovering over the object with a tooltip, the tooltip will follow the mouse if true. If false, it will be positioned relative to the object.
    content'title'Attribute containing the tooltip content. By default it is the "title" attribute.
    speed300Time in milliseconds for the tooltip to fade in. By design the tooltip has no fade out because it is removed immediately.
    localfalseWhere the tooltip is attached. By default it is false and will attach to the document body; if true, it will be attached before the object.
    xOffset20Number of pixels between the tooltip and the mouse (or object if followMouse = false) in the X direction.
    yOffset20Number of pixels between the tooltip and the mouse (or object if followMouse = false) in the Y direction.
    zIndex1000Adjust this if the tooltip is below another object.
    livefalseSet to true if you add tooltip objects to your page dynamically (added after the page is loaded).
    metadata'class'Location of the tooltip metadata. By default it will look in the class attribute. If set to "false" it will disable the metadata.
    activate'mouseenter focusin'The event that causes the tooltip to display information.
    deactivate'mouseleave focusout'The event that causes the tooltip to be removed.
    tooltip'.tooltip'The class used to activate the tooltip. And the ID of the actual tooltip.
    screenshot'a.screenshot'The class used to activate the screenshot script which shows an image associated with the URL. And this is the ID of both the screenshot & preview tooltips.
    preview'a.preview'The class used to activate the preview script which shows the an image in the tooltip from the href.
    tooltipId'tooltip'The ID of the actual tooltip.
    previewId'preview'The ID of the actual preview/screenshot tooltip (the share the same one).
Known Issues
  • Fixed:If the tooltip contents go out of the viewport, the script attempt to adjust the tooltip to make it visible. If it moves the tooltip under the mouse, the tooltip will flicker and become unreadable. This occurs when the east or west direction is used, so limit use of 'east' when the tooltip is near the right side and 'west' when it is near the left. I'll look into fixing this problem in future versions.
  • The tooltip script won't obtain cross-domain ajax requests by default, but I have included James Padolsey's cross-domain ajax script (jquery.xdomainajax.js) which should enable it. Just include the script in the head of your document.
  • If you find any other issues, please submit an issue to Jatt's github repository.

Saturday, July 10, 2010

How to click on a drag/sort object

I've seen this question come up a few times on Stackoverflow. How can I make a draggable/sortable/resizable/selectable object clickable as well?

You can use the built in event timestamp to determine the time difference between when the mouse down and mouse up events occur. Here is a basic demo of a sortable list that contains hidden content - clicking on the header "Content #" will open the hidden below. Holding the mouse down on the header will allow you to sort the list.

This is a basic list which contains a header (h3) and a hidden div.
<ul id="sortable">
<h3>Content 1</h3>
<div class="hidden">Some Content</div>
<h3>Content 2</h3>
<div class="hidden">Some Content</div>
<h3>Content 3</h3>
<div class="hidden">Some Content</div>
<h3>Content 4</h3>
<div class="hidden">Some Content</div>
<h3>Content 5</h3>
<div class="hidden">Some Content</div>
This css sets the styling of the list and hidden content.
/* set list width & remove bullets */
#sortable {
width: 500px;
list-style: none;
/* clickable header */
h3 {
font-size: 20px;
width: 200px;
background: #444;
margin: 5px;
padding-left: 5px;
/* header with revealed content */
h3.opened {
background: #0080c0;
/* hidden content */
.hidden {
display: none;
min-height: 100px;
background: #444;
color: #ddd;
padding: 5px;
I've included a lot of inline comments in the script which I hope makes it clear as to what it does.
Updated code (9/24/2010 - Demo) - added mouse move flag:
var last, diff, moved,
clickDelay = 500; // millisecond delay
// make the list sortable
// make h3 in the list "clickable"
.bind('mousedown', function(e){
// set time on mousedown (start of click)
last = e.timeStamp;
// clear moved flag
moved = false;
.bind('mouseup mousemove', function(e){
    // flag showing that the mouse had been moved
    if (e.type == 'mousemove') {
     moved = true;
     // no need to continue
// find time difference on mouse up (end of click)
diff = e.timeStamp - last;
    // check moved variable, to ignore click if the mouse had been moved (dragged)
    // if time difference is less than delay, then it was a click
    // if time difference is greater than the delay, then it was meant for dragging
if ( !moved &&  diff < clickDelay ) {
// toggle the opened class and the hidden content
Original code - Demo:
var last, diff,
clickDelay = 500; // millisecond delay
// make the list sortable
// make h3 in the list "clickable"
.bind('mousedown', function(e){
// set time on mousedown (start of click)
last = e.timeStamp;
.bind('mouseup', function(e){
// find time difference on mouse up (end of click)
diff = e.timeStamp - last;
// if time difference is less than delay, then it was a click
// if time difference is greater than the delay, then it was meant for dragging
if ( diff < clickDelay ) {
// toggle the opened class and the hidden content
  • In case you don't understand what's going on, a click is basically composed of a mousedown event and a mouseup event. The time difference between the two events is how you can determine if you have clicked or just pressed the mouse button to select text or drag an object around (like in this demo).
  • So in this script, the "last" variable contains the time stamp of the mouse down event
  • The "diff" is the time difference from the mouseup event and the last variable time.
  • I picked a default of 500 milliseconds for a mouse click delay (reference) for really slow clickers, but you can adjust it to anything you want.
  • If the time difference is less than 500 milliseconds then we can determine that the user clicked and preform the appropriate action (toggle the hidden content).
  • If the time difference is greater, then the user is probably trying to sort the list.
  • You could potentially add another action if the time difference is greater than the delay, but the script wouldn't do anything until the user released the mouse (mouseup event). But then you could bind a "mousemove" event that checks the timer against the "last" variable to find out how long the user has been clicking the mouse.
  • Update (9/24/2010): The newer script added above the original adds a mouse move flag that ignores the timer if the user moved the mouse during the click.

Friday, July 9, 2010

Visual Navigation

There are a few sites that have a navigation menu that can highlight / change when the menu's target scrolls into view (e.g. brizk design & Crush + Lovely) . I tried to generalize the script so it would work with any site and I ended making up with this jQuery plugin.

I set up a demo page here.

Download: Uncompressed | Minified | Zipped Demo | Github

I have tested this plugin in IE8, Firefox and Chrome. Please leave me feedback if you any problems with how it works or if it doesn't work in other browsers.

  • This plugin requires jQuery in order to function properly.
  • Follow the basic templates below to set this up on your site. For more details, go to the specific section.
Default Setup
  • HTML
    <div id="sidemenu">
    <li><a href="#home">Home</a></li>
    <li><a href="#work">Work</a></li>
    <li><a href="#blog">Blog</a></li>
    <li><a href="#projects">Projects</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#contact">Contact</a></li>
    • Change the side menu id to whatever you want, just make sure you target it with the script.
    • This side menu example will work with the plugin's default settings. See the alternate example of a different layout.
  • CSS
    #sidemenu { position: fixed; top: 50px; left: 20px; background: #444; width: 120px; }
    #sidemenu ul { list-style-type: none; margin: 0; padding: 0; }
    #sidemenu li { margin: 5px; padding: 5px; width: 100px; text-align: center; }
    #sidemenu li.selected { background: #555; }
    #sidemenu a { text-decoration: none; color: #bbbbff; }
    #sidemenu a:hover { color: #fff; }
    • This CSS highly variable. Change the position, size and colors as desired.

  • Script
Alternate Setup
  • HTML
    <div id="menu">
    <div class="link" title="#Home">Home</div>
    <div class="link" title="#work">Work</div>
    <div class="link" title="#blog">Blog</div>
    <div class="link" title="#projects">Projects</div>
    <div class="link" title=".about">About</div>
    <div class="link" title=".contact">Contact</div>
    • This side menu uses divs with a title attribute. The value in this attribute can be used to target an Id or a class (which should be unique).
    • It is important to note, that this menu will not work with javascript disabled, whereas the default one will work.
  • CSS
    #menu { position: fixed; top: 50px; left: 20px; background: #444; width: 120px; }
    #menu div.link { margin: 5px; padding: 5px; width: 100px; text-align: center; }
    #menu div.selected { background: #555; }
  • Script
    link              : 'div.link',
    targetAttr        : 'title',
    selectedAppliedTo : 'div.link'
Customizing / Options
This plugin has the following default options, so you will only need to include the line below in the script options if you want to change the default:
link              : 'a',        // Add a link class, as necessary
targetAttr        : 'href',     // added in case you have link = "div" and attribute something like
selectedClass     : 'selected', // css class applied to menu
selectedAppliedTo : 'li',       // to only apply to the link, use "a"
topRange          : 100,        // measure from the top of the viewport to X pixels down
topMargin         : 100,        // margin above the top where the target updates the menu
bottomMargin      : 20,         // margin from the end of the page where the last menu item is used
animationTime     : 1200        // time in milliseconds
  • The first four options should were hopefully made clear in the examples above.
  • To modify how the menu acts, you will need to adjust the "topRange", "topMargin" and "bottomMargin" values. I made this picture to better understand what these values do for you.
  • topRange: The "topRange" is basically the area where target needs to be inside of in order for the menu to update. For example, the target (found in the link attribute) starts under the topRange. As it moves up and crosses into the topRange. The script then updates the side menu to show that the target area is in view (or inside the view port).
  • topMargin: The top edge margin (topMargin) is the area above the view port. The top edge margin is used while the page is being scrolled up - the target is above the view port and as you scroll up, the target moves down. When the target is inside the edge margin, the menu will update and point to that target.
  • bottomMargin: The bottom edge margin is the area below the view port. It is when the page is scrolled down (the contents are moving up). When the bottom of the page is inside the bottom edge margin, the menu will update with the last targeted id. This was necessary to be include in case the last section is too short and unable to reach the top range area.
  • animationTime: The animation time is the time in milliseconds that the menu will scroll to the selected section.
Known Problems / Bugs / Suggestions
  • The menu will not select (or highlight) the item above the last item if they are both very short. For example, if your browser shows three sections while at the bottom of the page. The third to last may have shown for a brief time just before the bottom of the page reached the bottom edge margin. The menu would then skip directly to the last menu item. This is one reason why the bottom margin value is kept a low number (20 pixels by default).
  • If you click on a menu item, the page contents will automatically scroll to that section and update the browser url with that target. But if you manually scroll the page using the scroll bar or mouse, the web page url will not update with the current position. This was done on purpose, because if the script changes the location, the page will jump to that target automatically. This wouldn't look good if you are quickly scrolling through the page as it would make the movement jittery.
  • To make suggestions or report any bugs please email me at wowmotty at g mail dot com.

Sunday, July 4, 2010

todaysImage v1.0

The plugin will take a group of images which have a set date range, and show an image randomly from the group depending on the current date. It is based on my original Random Image by Date script but has been significantly modified and improved! It's shiny and sparkly, but you won't be able to tell much difference on the surface.

The frame below contains a demo of this script... you can view the page directly by clicking this link so you can more easily understand what it does and test the debuging features.

Download: Uncompressed | Minified | Zipped Demo (2.5Mb - includes all images) | Github


The set up is fairly simple (I hope). The page requires three things to work:
  1. jQuery loaded (you can use Google's copy as seen in the page source).
  2. An <img> anywhere on your page.
  3. Data source consisting of a date range and image url. You can also include optional comments.
Data Format

To include an image in this script, you will need the following bits of information:
  • Date (required) - Use the format below
  • Image URL (required)
  • Comment (optional)
  1. Date format (do not include the year):

    0Set image as a default (will only display if no date specific images are found).
    1/1 Dispaly image only on Jan 1st.
    1/1 - 1/5Dispaly image from Jan 1st to Jan 5th (spaces are okay).
    7/20 - 8/20Display image from June 20th to August 20th.
    1/3rdMonDisplay image only on the 3rd Monday of January.
    5/lastMonDisplay image only on the last Monday of May.
    11/3rdThur-11/4thThurDisplay image from the 3rd Thursday of Nov to the 4th Thursday of Nov.
    12/20-1/1stSunDisplay image from Dec 20th to the 1st Sunday of January.


    • The dates that cross months (7/20-8/20) will display along with date specific images (added to the randomization).
    • Use slashes "/" to separate the month and day and dashes "-" to set a range (e.g., using "1-1 to 1-5" will break the script)
    • Using the last weekday (lastMon) of the month in the date has one restriction at this time... it'll only works for 30 day months for now. I may fix this in future versions.
    • When using the text in the date (e.g. 1st, 2nd, 3rd, last) don't spell these fully out ( first, second, third) as the script is looking for the number and not the text.
    • The weekday in the date must have at least 3 letters - these are okay: (Mon or Monday); these are not okay (M or Mo).

  2. Image URL - Umm, yeah it's required.

  3. Comment (optional)

    • The image comment will be added to the image title (or not, as desired) or into any HTML tag using an ID or class name.

    • The script is set up so that the comment can include HTML elements to add styling, but be careful to not use quotes. The script does replace quotes with the HTML escape code " but this doesn't guarantee it will work once viewed in the comment div.
Data Sources
  • This plugin is set up to accept data from a jQuery selector (for data contained in HTML), an array or a JSON variable that is inline or retrieved remotely.
  • There is an example how to accomplish each method below and there is also a demo of each (included in the zipped file).
  • The examples below expect an image with the ID of "todaysImage"
  • All data should be presented to the script in this order: date, url, comment; you can change this order, but it will require additional option settings, described later.
  • There is no need to maintain the exact chronological order of the data. I tried to keep them this way in the demo to make finding dates easier.
  • All script should be wrapped in a $(document).ready function.
  1. HTML

    • The data can be stored in an HTML list. You point your jQuery selector at the list and tell it which attributes have the data.
    • Here is an example list (hidden using CSS):
      <ul id="myImageList">
      <li rel="0" title="images/main1.jpg">Hello</li>
      <li rel="0" title="images/main2.jpg">Hello</li>
      <li rel="12/31-1/5" title="images/new-year.jpg">Happy New Year!</li>
      <li rel="5/1-8/5" title="images/Summer.jpg">Summer time!</li>
      As you see, the list is stored in an <li> tag with the date in the rel attribute, the url in the title attribute and the comment inside the tag. This is how to set the script to gather the data correctly.
      data       : $('#myImageList li'),
      dataObject : ['rel', 'title', 'html'] // these must be in this order: [date, url, comment]
      The 'rel' and 'title' parts of the dataObject are attributes of the tag while the comments needs either a 'text' or 'html' to target its data; use 'html' as in the example, if you have included any styling in your comment.

      NOTE: As stated before the order of the dataObject is important - [ date, url, comment ]

  2. ARRAY

    • An array can be set up, as I did in my original script, to contain all of the data needed for this script.
    • Once again, the order these are placed in the array are important, here is a basic template:

      images.push (["DATES","IMAGE URL", "COMMENT"]);

    • Here is an example:
      var images = [];
      images.push(["12/31-1/5","images/new-year.jpg","Happy New Year!"]);
      images.push(["5/1-8/5","images/Summer.jpg","Summer time!"]);
      the script below will access this data. Notice the dataObject option sets the order of the image array. If you already have an array with similar data, all you need to do is set the dataObject to point to the correct index so that this order is maintained [ date, image URL, comments ] (e.g. images.push([ "comment", "other data", "dates", "url' ]), would required the dataObject to be [2, 3, 0]).
      data        : images,
      dataObject  : [0,1,2]
  3. JSON - inline

    • I use this method when I have a short list and want to save myself a server call.
    • Take a standard JSON object and just add "var json =" in front of it.
    • If you already have a JSON set up but it has different names (or even a different language) then just adjust the dataObject as needed
    • Here is a basic template:
      var imageList = {"images": [
      "dates"  : "0",
      "image"  : "images/main1.jpg",
      "comment": "Hello"
      "dates"  : "0",
      "image"  : "images/main2.jpg",
      "comment": "Hello"
      "dates"  : "12/31-1/5",
      "image"  : "images/new-year.jpg",
      "comment": "Happy New Year!"
      "dates"  : "5/1-8/5",
      "image"  : "images/Summer.jpg",
      "comment": "Summer time!"
      The script below will access this data. Notice that "imageList" matches the variable and "images" matches the very first name in the JSON object (the key). The dataObject by default is [ 'dates', 'image', 'comment' ] which matches the JSON above; but if you have a JSON object that has different key names like "dateRange", "imageURL" and "imageComment", then you will need to set the dataObject appropriately to [ 'dataRange', 'imageURL', 'imageComment' ].
      data: imageList.images
  4. JSON - remote

    • Use this method to load JSON from your server. It won't work cross domain (unless you have it setup to work with JSONP)
    • This method requires your JSON to be valid, or the object won't parse properly (this includes removing all comments)
    • This JSON, as stated before, is essentially the same as the JSON inline.
      {"images": [
      "dates"  : "0",
      "image"  : "images/main1.jpg",
      "comment": "Hello"
      "dates"  : "0",
      "image"  : "images/main2.jpg",
      "comment": "Hello"
      "dates"  : "12/31-1/5",
      "image"  : "images/new-year.jpg",
      "comment": "Happy New Year!"
      "dates"  : "5/1-8/5",
      "image"  : "images/Summer.jpg",
      "comment": "Summer time!"
      Access this remote JSON data as follows:
      $.getJSON( 'images.json', function(imageList){
      data: imageList.images
      The JSON data in the example is from the file "images.json". Replace this with the URL pointing to your data. I used "imageList" as the JSON data to show the similarities to the JSON inline method. Of course "images" is the first element (key) in the JSON object, and the dataObject doesn't need modification as the names in the JSON object match.
This plugin has the following default options, so you will only need to include the line below if you want to change the default:
data         : '', // dataObject contains the date, image and comment names as seen in the data (names if JSON, numbers [0,1,2] in an array)
dataObject   : ['dates','image','comment'],
comment      : '.imageComment', // class or id where the current image comment will be added; if it doesn't exist, no comment will be shown
noImageTitle : false,           // if true, the script will not add the comment to the image's title attribute

/* language options */
dayEndings : 'st|nd|rd|th',  // 1st, 2nd, 3rd, 4th, etc. (e.g. 1stMon & 3rdThu)
dayLast    : 'last',         // last weekday/weekend of the month
dayWeek    : ['sun','mon','tue','wed','thu','fri','sat'], // days of the week (case insensitive)

/* debugging options */
locked          : false,// prevent debug mode onscreen output if true (debug setting from browser URL only).
debug           : false,// set debug mode.
debugId         : 'imagedebug', // id of the debug output div - all info and show all images will be added here.
debugElement    : 'body',       // Location where debug id is added (where debugId div is appended)
defaultDate     : '1/1/2010',   // date used if setting debug mode but no default date.
inRangeColor    : '#080',       // color highlight (green) for signifying the date is in range.
notInRangeColor : '#f00'// color highlight (red) for dates not in range.
dataPlease refer to the Data Sources section above on how to set this data
dataObjectPlease refer to the Data Sources section above on how to set this data
commentThis option targets the class or Id of an HTML element where you want the current image comment to be displayed, if this target doesn't exist, no comment will be shown
noImageTitlePrevent the script from adding the comment to the image title. Done if you want to apply a tooltip to the image to display the message
dayEndingsAbbreviation suffixes for 1st, 2nd, 3rd, 4th, etc. The script actually only uses these to match the date string, but they are ignored otherwise. So if you mistakenly add 4rd, it will use the 4 and not the "rd"
dayLastString used to match and causes the script to find the last weekday/weekend of the month (e.g. lastMon)
dayWeekList of days of the week. It is used to match the weekday from the data date, so this is language agnostic, but the first day of the array must start with sunday to match the javascript date method. Limit these names to three letters and the letter case doesn't matter.
monthFirstSet to true (default) to use standard US date formatting - mm/dd/yyyy. If set to false, the European date format can be used - dd/mm/yyyy.
lockedLocks out using the debug mode from the browser address bar (adding "#debug" to the url will enable debug mode if the script isn't locked, like my demo)
debugEnable debug mode through the script. This value is set to true if the script is not locked and "#debug" is added to the url. This mode will display image data to show matches found and date ranges. For more detail, see the troubleshooting section below
debugIdThis is the Id of the element to find to output the debug data. If it doesn't exist and debug mode is initiated, a div with this Id will be added to the debugElement (see below) which by default is the document body. If using the showAll() method above, this element will need to me manually added before images will be displayed.
debugElementBy default, the debug element is the document body. This is where the debugId div is appended, if it doesn't exist, when debug mode is initiated.
defaultDateThis date is only used if the debug mode is initiated by the script and no other date is supplied. The default date for the debug mode when adding it to the url would be the current date unless otherwise specified - see the troubleshooting section below for more details
inRangeColorText color applied to the debug text when an image date is in range (green by default)
notInRangeColorText color applied to the debug text when an image date is not in range (red by default)

You can get, set, find current number or have the script choose another random image as follows:
  • Get current image data

    • Use the "currentImage()" method to get this data.
    • This method will return an array of the currently displayed image's date, url and comment (in that order).
    • The second line was added to show how to target the image url.
    var current = $(image).data('todaysImage').currentImage(); // returns array ['dates','image url','comment']
    alert( 'current image url = ' + current[1] );
  • Set/Get current image

    • Add a number to the "currentImage()" method to set the image. An array of the image is returned (as above).
    • Setting a number that is greater than the number of images in the date range will cause the image to wrap around back to the beginning
    // Sets displayed image to the first (zero based index) image that falls within the date range,
    // then returns array ['dates','image url','comment'] of that image
    var current = $(image).data('todaysImage').currentImage(1);
  • Get current number of images

    • Use the "currentNumber()" method to get this information.
    • This value is the number of images with a date range that covered the date (e.g. if the date is 12/24, the demo script will find 8 images from which to choose)
    // return the number of images that have date ranges that match the date
    var currentNumber = $(image).data('todaysImage').currentNumber(); // returns a number
  • Random Image

    • Use the "randomImage()" method to display another random image.
    • This method will return an array of the currently displayed image's date, url and comment (in that order).
      $(image).data('todaysImage').randomImage(); // displays a random image in the date range & returns array
  • Show All Images

    • This method is used by in edit mode when clicking on the "Show All Images" button. It is useful for checking that all the image urls are correct and all the data is valid.
    // Show all images in the data, the script targets the id found in "debugId" option
    • This method will not work if the element targeted by the "debugId" option doesn't exist. By default, the "debugId" is "imagedebug" which is added while the script is in debug mode. But if you want to display a list somewhere else, just make sure the target exists (Id only, no class) and change the "debugId" option to match it.
      #allImages img { height: 100px; width: 100px; } /* make images thumbnail size */
      <div id="allImages"></div>
      // initialization of script
      // other options here, including data source
      debugId : 'allImages'
    • If you are noticing that one image isn't showing up or something just doesn't work right, you can try to trouble shoot the problem.
    • Initiate the debug mode in the script as follows:
      // initialization of script
      // other options here, including data source
      debug: true,
      defaultDate: '12/24/2010' // choose any date using this format
    • Additionally, you can access the debug mode from the address bar simply by adding the following (in blue) to the end:


      • #debug - actives the debug mode
      • 12/31/2009 - sets the date you want to check (month/day/year)

      To prevent debug from working once you are done with your script, simply set the locked variable in the script to true:
      // initialization of script
      // other options here, including data source
      // locks out debug mode from the URL
      locked: true
    • Sample debug output:
      Date used: 11/20/2009
      (11/11), derived range: 11-11 is NOT in range; image = veterans1.jpg
      (11/11), derived range: 11-11 is NOT in range; image = veterans2.jpg
      (11/11), derived range: 11-11 is NOT in range; image = veterans3.jpg
      (11/3rdThur-11/4thThur), derived range: 19-26 is in range; image = thanksgiving1.jpg
      (11/3rdThur-11/4thThur), derived range: 19-26 is in range; image = thanksgiving2.jpg
      (11/3rdThur-11/4thThur), derived range: 19-26 is in range; image = thanksgiving3.jpg
      (11/3rdThur-11/4thThur), derived range: 19-26 is in range; image = thanksgiving4.jpg

      # of currentImages = 4
      current random image = thanksgiving4.jpg
    • Try out these links to see the debug mode in action (my example script isn't locked):

      1. #debug:1.1.2010
      2. #debug:10/31/2009
      3. #debug - This will default to todays date, but edit mode is active

Wednesday, June 30, 2010

ImageHighlighter v1.01

ImageHighlighter is an updated version of my original imgHighLighter plugin with lot of improvements! Most are under the hood so you probably won't see too much of a difference on the surface.

This plugin allows you to highlight a portion of an image when you hover over a link. In the image below, the mouse is hovering over the different links and you can see the corresponding portion of the image becomes highlighted (there is an animate gif below, but just click on the image to go to the demo page).
I set up an demo page here.

Download: Uncompressed | Minified | Zipped Demo | Github

I have tested this plugin in IE8, Firefox and Chrome. Please leave me feedback if you any problems with how it works or if it doesn't work in other browsers.

7/6/2010: Updated this post to describe v1.01 where the editor portion of the script was moved into a plugin extension. And support for jCrop was added to allow selecting the entire box instead of just getting the mouse coordinates. Check out the updated demo page!

  • This plugin requires jQuery.
  • HoverIntent is an optional plugin, this plugin will use it's functionality if it is included.
  • Follow this basic template with a quick summary for each image you want to apply imageHighlighter functionality. For more details, go to the specific section.

    <ul class="imgHL">
    <a href="#" rel="sx1,sy1,ex2,ey2">Item #1</a>
    <p>Description for item #1</p>
    <a href="#" rel="sx1,sy1,ex2,ey2">Item #2</a>
    <p>Description for item #2</p>
    <a href="#" rel="sx1,sy1,ex2,ey2">Item #3</a>
    <p>Description for item #3</p>
    <img id="imgHL" src="myimage.jpg" alt="" />
    <div class="description"></div>
    • In the HTML above, the highlight links are all wrapped in a div with a class name "imgHL" to make them easier to target.
    • The highlight links (<a>) must contain a rel attribute with the highlight box coordinates (see the Highlights section below for more detail).
    • Each link/description pair is wrapped together (inside an <li> in this case). See the Descriptions section below for more details.
    • The image is the central element. Once the script is initialized, the image will contain all of the plugin information. It is also the target of both the imageHighlighter and imageHighlighterEditor scripts.
    • The highlight description will be placed into the div with class "description". You can target a different class/Id when you modify the script options.

    CSS (basic example)
    /* List link: currently hovered/selected */
    a.current { color: #fff; }
    /* Hide & Position Descriptions */
    .imgHL p { display: none; }
    .description { margin: 1em auto; clear: both; width: 450px; height: 2.4em; }
    /* General imageHighlighter (overlay and highlight) */
    .imageHighlighter, .imgHLDark, .imgHLLight, .imgHLOverlay { padding: 0; margin: 0; } /* overlay and highlight divs */
    .imgHLOverlay { background: #000; opacity: .5; filter: alpha(opacity=50); } /* overlay color & opacity *
    • When a link is hovered and the image reveals the highlight box, the class "current" is applied to the link. You can use this to style the link and make it stand out.
    • The css definition ".imgHL p" hides the descriptions that appear under the image (in this example). The description is moved into the ".description" element when the highlight link is hovered.
    • The description class can be placed anywhere on the page; but because of this, the class name ".description" must be unique for each imageHighlighter instance on the page. You can easily modify this class name using the plugin options.
    • The general imageHighlighter definitions apply to the div wrapping the image (.imageHighlighter), the overlay (.imgHLOverlay & .imgHLDark) and the highlighted box (.imgHLLight). As you can see, the overlay has a background color and 50% opacity to darken the image behind the highlight. This can be set to transparent here in the CSS or disabled using the script.

    /* window load ensures all images are loaded */
    list : '.imgHL a'
    • This script uses "window.load" instead of "document.ready" to ensure that all images have been loaded. This is necessary as the script needs the image dimensions in order to initialize properly.
    • In this basic example, the highlight links are targeted using the ".imgHL" div that wraps the entire list. The default list setting is "a" which is much too general to use, but the script will ignore any link that doesn't contain a rel tag.
    • There are more options that can be set. For a full list and detailed descriptions, look under the customizing/options section!

  • Highlights: The highlight link's "rel" attribute contains all the information needed for the highlights.
    sx1Starting X position of the highlight box } top left corner
    sy1Starting Y position of the highlight box
    ex2 Ending X position of the highlight box} bottom right corner
    ey2Ending Y position of the highlight box
    You can change the highlight properties of each image using: borderColor, borderSize & borderType described in the Customizing/Options section below.

  • Image: The image must be targeted when initializing the script. You could target the class ('.imgHL') in the example above and the script will initialize once it has found the image from that group of selections. The image contains all of the data associated with this plugin, from using the built in methods to targeting custom events.
  • Descriptions: Each link/description pair should be wrapped together. In the demo where the links are in a paragraph, the link/description pairs are wrapped in a span:
    <span><a rel="sx1,sy1,ex2,ey2">Item #1</a><span class="desc">Description for Item #1</span></span>
    In the other example, the pair are wrapped inside of a list (<li>). Make sure that the descriptions are hidden and targeted by the "descrip" plugin option. The script will look inside the link highlight wrapper, so you don't necessarily have to have a specific class assigned to it as long as the element is unique (e.g. don't have two <p>'s inside with the highlight link otherwise the contents of both will be displayed in the description.

    The second part of the description is set using the "descripClass". The descriptions for the highlight will appear inside an element with this class, when hovering over a link. It can be located anywhere on the page, but the class/id needs to be set in the plugin options and unique for each instance of the plugin.

  • Overlay: The overlay covers the image (darkens the background) to make the highlighted portion stand out more. You can adjust the opacity of this overlay in the CSS and you can turn off the overlay functi0nality by setting the overlay option to false.
Customizing / Options
This plugin has the following default options, so you will only need to include the line below if you want to change the default:
borderColor : "#fff",         // highlight border color
borderSize  : 4,              // highlight border thickness
borderType  : "solid",        // highlight border type
list        : "a",            // links that contain the highlight coordinates (e.g. "li.imgHL a")
descrip     : "p",            // HTML tag sibling of the link, that contains the description text (hidden) (e.g. "p.desc")
descripClass: ".description", // HTML tag where description text is shown (placeholder)
overlay     : true,           // display an overlay to make the highlight stand out
current     : "current",      // class applied to link currently used to highlight the image
hoverTimeout: 100,            // hoverIntent timeout (only applied if hoverIntent plugin is loaded)
zindex      : 10              // z-index of highlight box, overlay is automatically made 1 less than this number
You can use the following methods to get and set the highlighted content. Note that these methods must target the image.
  • Get: In the following example, the variable current will contain the current link object that has been highlighted. If nothing is currently highlighted, the script will return null.
    var $current = $('#imgHL').data('imageHighlighter').highlight();
  • Set/Get:
  • Use a number (indexed from one: first, second, etc) - if the nth link doesn't exist, it will return null.
    var $current = $('#imgHL').data('imageHighlighter').highlight(1); // select the first link
  • Search for the case-sensitive text within the link (uses the jQuery ":contains()" selector) - if the text is not found, the script will return null.
    var $current = $('#imgHL').data('imageHighlighter').highlight("frames");
  • Search for the link with a class or ID - if the selector is not found, the script will return null.
    var $current = $('#imgHL').data('imageHighlighter').highlight(".box");
Edit Mode
  • Updated in v1.01:
    • The edit mode script was moved into an extension for the plugin. This was done because the edit script is not required once the coordinates are obtained and the script is deployed on your site.
    • Additionally, the script was made to work with the Jcrop plugin (included with the demo file zip) allowing you to use a resizable selection box to more easily get the coordinates.
    • If you click on the coordinates, the coordinates (contained in an input tag) become selected, so you can more easily copy them.

  • Edit mode for this plugin should make it easier to obtain the coordinates of the highlight box - the coordinates added to the highlight link rel attribute.

  • As of v1.01, edit mode can be activated by:

    1. Including the imageHighlighterEditor script & the jCrop plugin script, if desired.
    2. Set up the editor by calling the script on the same image(s) as the imageHighlighter script. You can generalize the call by targeting the ".imageHighlighter" class (applied to a div that wraps the image after the imageHighlighter script is applied to it). There is only one options, seen below:
      // Enable the editor and use the Jcrop plugin, if it is available
      $('div.imageHighlighter img').imageHighlighterEditor();
      // Enable the editor, but don't use the Jcrop plugin (even if it has been loaded)
      $('div.imageHighlighter img').imageHighlighterEditor({ useJcrop: false });
    3. Now activate or deactivate edit mode by double clicking on the image. A green bar (styled in the CSS) will appear below the image which will show the mouse coordinates (default editor) or the box coordinates (Jcrop plugin added).

  • With the editor active:

    • Default editor - move the cursor over the image to find the coordinates. Then clicking on the image will lock the coordinate display and make copying these numbers easier.
      Mouse x,y coordinates (click to lock/unlock) : x,y
    • Jcrop plugin installed - single click anywhere on the image to make the a corner of the box, then drag your mouse any direction to create a resizeable box. The coordinates of the upper left and bottom right corners of the box will display under the image:
      Current box coordinates : x1,y1,x2,y2
    • Click on the coordinates (they are inside an input tag). The contents will automatically be selected, but not copied.
    • When you hover over a highlight link, the highlight link name and coordinates from that link is displayed above the coordinate bar.
Bugs / Suggestions
  • When the window is repositioned, the highlights may be off until it is refreshed again when you hover over a link (especially while in edit mode), and sometimes you'll need to reload the page.
  • To make suggestions or report any bugs please email me at wowmotty at g mail dot com.

Monday, June 21, 2010

Moving Boxes Updated

Update (10/8/2011): A plugin is now available for WordPress for MovingBoxes v2.1.4, which you can download here or search for 'movingboxes' in your 'Install Plugins' page of your site admin section. More features and options will be added once craftyhub, the author, gets settled in :)

Update (10/13/2010): Version 1.5 now available!

I've updated the Moving Boxes script by Chris Coyier by converting the script into a plugin so now you can add multiple Moving Boxes blocks on the page at one time.

I haven't done extensive testing of the script, so if you find any bugs please feel free to contact me.

Download: uncompressed | minified | zipped file | github (see a demo!)

  • Use these key : value pairs as follows; Note that the last key : value pair does not have a trailing comma
<script type="text/javascript">
$(selector).movingBoxes({ key: value, key: value, key: value })
(default shown)
startPanel1Choose the initial panel to show in the scroll window.
width800Overall width of movingBoxes.
panelWidth.50Current panel width adjusted to 50% of movingBoxes width.
reducedSize.8Non-current panel size: 80% of current panel size.
imageRatio4/3Image ratio set to 4:3. Wide screen would be 16:9 (16/9).
speed500Animation time in milliseconds for the scroll and expanding of the panel.
hashTagstrueIf true, hash tags (browser history) are enabled.
wrapfalseIf true,the panel will "wrap" at the ends.
Panels are numbered as a standard index (1st panel number is one, second is two, etc.).
  • Get number of currently selected panel:
  • Set currently selected panel:
External controls:
$('.slider').data('movingBoxes').goForward(); // go forward one slide (if possible)
$('.slider').data('movingBoxes').goBack();    // go back one slide (if possible)

    Saturday, June 19, 2010

    Progress Indicator

    I wrote this plugin to allow more control over the progress indicator. To the right is an animated gif progress indicator. All you can do is show or hide this image. This plugin allows you to make a similar indicator that you can fully control. The plugin will animate both text (including bullets) or images, I guess you could also animate embedded objects, but I haven't tested this. The reason I call this progress indicator dynamic is you can modify or update the objects in the indicator at any time (e.g. replace images or text while the indicator is active). I'll make a demo of this when I have more time :)

    In the demo below, you can start or stop the timer to make the progression indicator simulate the animated image or you can move the slider to animate the indicator.

    Download: uncompressed | minified | zipped file | github
    (zip includes demo; go to link, then download... I'm not sure why you can't download it directly)

    • CSS (basic setup)
      .progress {
      position: relative;
      top: 0;
      left: 0;
      width: 200px;
      height: 200px;
      overflow: hidden;
      .progress span {
      position: absolute;
      left: -50px; /* hide spans until initialized */
      top: 0;
      padding: 0;
      margin: 0;
      border: 0;
      .display {
      position: absolute;
      top: 95px;
      left: 90px;
    • HTML
      <div class="progress">
      <!-- this displays the percent value, position in the middle with CSS -->
      <div class="display"></div>
      <!-- add as many <span>s as you want, add any text or image inside -->
    • Script - Initialization
      <script type="text/javascript" src="jquery.progressindicator.min.js"></script>
      <script type="text/javascript">
      // initialize: initialValue is uaually zero, and a full list of "options" can be found below.
      $(selector).progressIndicator( initialValue, options );

    List of Default Settings:
    • Use these key : value pairs as follows; Note that the last key : value pair does not have a trailing comma and values that use true or false (Boolean values) should not be in quotes.
      $(selector).progressIndicator( initialValue, { key: value, key: value, key: value })
      (default shown)
      max100The circle is split into this max number of increments (default set to 100 to match a percentage going from 0-99).
      radius50Sets the radius of the circle in pixels measured from the centerX and centerY position (middle).
      centerX100Positions the center of the circle 100 pixels from the left edge of its container.
      centerY100Positions the center of the circle 100 pixels from the top edge of the container.
      clockwisetrueSets the direction of the rotation. Clockwise if true and counter (or anti for you British folk) clockwise if false.
      startPosition0.75This may not make sense if you don't know the coordinate system, but basically zero is the far right side of the circle or the x-y coordinates of ( x=radius, y=0 ) . So if you want to have the indicator start with the "zero" at the top of the circle, you need to start from 75% or 3/4 of your way around the circle. So basically, set 0 to start on the right, .25 (25%) for bottom, .5 (50%) for left and .75 (75%) would be the top of the circle where ( x = 0 , y = radius ).
      sizeStart80Sets the starting size of the element to 80 pixels. This sets the font size, the height & width of any element inside the span (like an image)
      sizeDec4Sets how much to decrement the size of the next element from the starting size. Try to avoid making the decrement size that would cause the last element to be too small or negative (for example: these settings would not look good, 10 spans inside the progress indicator (in the HTML), sizeStart = 20, sizeDec = 2; this would make the last span element have a size of zero (20 - 2 * 10 = 0).
      showValuetrueAdds the progress indicator value to the "display" class inside the progress div. If you want to be tricky, add the display class to one of your spans to have the indicator move around with the other elements.
      timerActivefalseInitialize progression indicator start and stop functions allowing the indicator to move independent of the percent value.
      timerSpeed20Sets the setInterval time in milliseconds.
      timerIncrement1At each setInterval call, the progression indicator is incremented by this value. Make this number bigger to speed up the animation, but the bigger the number, the more choppy the animation.

    • Get & Set Progression Value
      // Get current value (percentage)
      var value = $(selector).data('progressIndicator').getValue();
      // Set/Update current value
      $(selector).data('progressIndicator').update( value );
    • Animation timer functions (the timerActive option must be true before these will work)
      // Start animation timer
      // Stop animation timer
      // Reset animation timer (just resets position)
    Examples - Be sure to look at the demo source to see some other examples of what is possible!
    • These examples should be wrapped inside of a:

      $(document).ready(function(){ ... })

      replace the ellipsis (...) with the script in the column below.
    Action Script Notes:
    Set up timer, so the start & stop methods are available. And adjust animation speed. $('.progress').progressIndicator(
    0, {
    timerActive : true,
    showValue : false,
    timerSpeed : 20,
    timerIncrement : 1

    The zero in the first line sets the initial position of the indicator, it's not really that important for the animation timer mode, but necessary to include.

    "timerActive" enables the start and stop timer methods. "showValue" is set to false to hide the progression value. "timerSpeed" and "timerIncrement" were adjusted to make the progression animation fairly quick. In the demo they are set to 50 and 5 respectively so you can see how much faster you could make this animation without it being too choppy.
    Rotate counter (anti) clockwise & other adjustments$('.progress').progressIndicator({
    clockwise : false,
    startPosition : .32,
    sizeStart : 5,
    sizeDec : -1
    Setting the clockwise option to false with reverse the indicator rotation. Note that reversing the direction also effects the "startPosition" so you may need to adjust this value as well. This example is from progression3 in the demo and it needs a startPostion of .32 (32%) to move the images to the top... the reason it isn't 25% is because the sizeStart begins small (5 pixels) and the sizeDec is negative so this actually increases the image size as it progresses through the elements. You'll probably end up tweeking these numbers to get the look you want.
    Max value$('.progress').progressIndicator({
    max : 200
    By default, the progress indicator is set to work with percentages.. it really only goes from 0 to 99%, but by changing the max option, you can set a full rotation of the progress indicator to any value. Note, the value, set using the update method, and the max value can be fractions.

    Monday, May 17, 2010

    Drag External Events Into fullCalendar

    Update: FullCalendar now supports dragging external events into the calendar, but the external events don't include any event data =(

    I want to first preface this post with this fullCalendar ticket where the author provides a github branch with a fullCalendar version, but he hasn't officially integrated the code into the main plugin as of yet.

    I didn't want to use the non-supported version, so I wrote this plugin that essentially does that same thing. But this version only allows you to add external events to fullCalendar while it is in month mode. The author's version allows you to drop external events into the calendar while it is in any mode (month, week, day, etc). The reason is because this plugin will work with any version of fullCalendar, while the author's version would require that you use the unsupported code.

    So, until fullCalendar officially releases a version that allows dragging in external events, you could consider using this plugin.

    Download ( uncompressed | minified ) : Demo

    • Required scripts

      1. fullCalendar plugin
      2. jQuery library
      3. jQuery UI Draggable, Resizable & Dialog components
      4. jQuery metadata plugin (optional)

    • CSS

      1. fullCalendar CSS (included with the plugin, but you will need to modify it if you want to use different colors (or set the calendar to use jQuery UI themes)
      2. jQuery UI theme
      3. Any additional CSS to position the external event panel (view the demo source for some basic settings)

    • HTML (basic setup with variations)

      <ul id="eventsToAdd">
      <li class="fc-event"><span data-id="holiday" class="title" data-start="8a" data-end="4p">Holiday</span></li>
      <li class="fc-event"><span data-id="host" class="title {start: '7p', end: '10p', title: 'Get drunk!', duration : 2}">Hosting Event</span></li>
      <li class="fc-event"><span data-id="meeting" class="title" data-title="Nap Time!">Meeting</span></li>
      <li class="fc-event"><span data-id="party" class="title" data-allDay="false">Party</span></li>
      <li class="fc-event"><span data-id="plan" class="title" data-start="5pm" data-end="7p">Planning Session</span></li>
      <li class="fc-event"><span data-id="vacation" class="title" data-allDay="true" data-duration="7">Vacation</span></li>
    • Script Setup (default settings shown)

      $('#eventsToAdd li').fcExternalEvents({
      calendar         : '#calendar',      // Selector string that points to the calendar object
      newEventObject   : 'span.title',     // Contains all event data (store in metaData or in data-'attr' as seen in the HTML)
      workDayStart     : '8a',             // use any time format '8','8a','8am','8 a.m.','0800','8:00' -> '08:00:00'
      workDatEnd       : '4pm',            // use any time format '4','4p','4pm','4 p.m.','1600','16:00' -> '16:00:00'
      draggableOptions : { revert: true }, // Available options: http://jqueryui.com/demos/droppable/
      useMetaData      : true,             // If plugin exists get metadata from class (plugin: http://docs.jquery.com/Plugins/Metadata)
      metaDataOptions  : {},               // use this if you put the metadata anywhere beside inside the class attribute (http://docs.jquery.com/Plugins/Metadata/metadata#options)
      editExternalEvent: true,             // true: allows you to click on an external event to edit it's data.
      addExternalEvent : true,             // true: allows you to add an external event to the list.
      disableConfirm   : false             // true: disables the confirmation popup when you try to delete an event.
    • Script for Event Triggers (used to update your database)

      • External Event added to FullCalendar - triggered on the calendar itself

        // *****************************************
        // External event added to fullCalendar event trigger
        // *****************************************
        // fcEventObject  = fullCalendar event object
        $('#calendar').bind('ExternalEventAddedToFullCalendar', function(event, fcEventObject){
        updateDisplay('Event added to fullCalendar: ' + fcEventObject.title );
      • Add, Update or Delete an External Event - triggered on external event container

        // *****************************************
        // External Event triggers:
        // Add, update and delete are triggered on the PARENT element!
        // *****************************************
        // External Event Added/Updated
        // ********************
        // externalEventElement = jQuery object targeting newly added draggable event
        // fcEventObject  = fullCalendar event object
        .bind('ExternalEventUpdated ExternalEventAdded', function( event, fcEventObject, externalEventElement ){
        var whichEvent = ( event.type == 'ExternalEventAdded' ) ? 'added' : 'updated';
        var txt = 'External event ' + whichEvent + ':' + externalEventElement.find('span.title').text() + ' (' + fcEventObject.title + ')';
        updateDisplay( txt );
        // External Event Deleted
        // ********************
        // externalEventElement = jQuery object targeting newly added draggable event
        // fcEventObject  = fullCalendar event object
        .bind('ExternalEventDeleted', function(event, fcEventObject, externalEventElement ){
        var txt = 'External event Deleted:' + externalEventElement.text();
        updateDisplay( txt );
      • fcEventObject - Please refer to the FullCalendar Event Object documents for details.
    • HTML data

      Inside of the "newEventObject" (<span> contained inside of the <li> in the HTML above) you can add data in three different ways:

      1. Add a data-[name] attribute supported by HTML5. Each Full Calendar Event Object property key should replace the [name] so you'll end up adding these data attributes:

        Event ObjectData attributeType
        allDaydata-allDaytrue or false (Boolean)
        startdata-startString (time only) - The external event script adds the correct month, day & year
        to the event after it is dropped on the calendar
        enddata-endString (time only) -The external event script adds the correct month, day & year
        to the event after it is dropped on the calendar
        urldata-urlString - the editor does not validate the URL.
        editabledata-editabletrue or false (Boolean)
        durationdata-durationInteger (# of days) - This attribute is used by the external event script to determine
        the end date of an event. It might be best to also set the "allDay" attribute to true
        if this value is more than one.

        For more details see the FullCalendar Event Object Documentation.

      2. Add metadata contained inside of the class attribute, as in this example:

        <span class="title { id: 'event1', title: 'My Event', allDay: false, start: '1pm', end: '2pm' }">My External Event Name</span>

      3. Add data using this plugin's Add or Edit Event functions

        When adding or editing an external event, a few more event options are listed. These include the "Event Location" & "Event Description" which are part of the google calendar event object, but not standard in FullCalendar, so some customizing of FullCalendar would be required to see this part of the data. It is added here in case you are using google calendar events.

        You will also notice a checkbox that is labeled "Make id unique". By default this is checked. What it does is adds a date stamp to the end of the id so that adding multiple copies of one event will move separately when dragging and dropping on FullCalendar. You can try it out by adding two copies of any event, when you attempt to move the event around in fullCalendar, both events will move, keeping the number of days between events the same - if you don't understand my description, just try it out in the demo :)

      If a piece of data is not listed in the data-[name] or in the metadata then it will be set to its default value when added to the FullCalendar.

    • List of Standard Options:

      Use these key : value pairs as follows; Note that the last key : value pair does not have a trailing comma and values that use true or false (Boolean values) should not be in quotes.

      $('#listWrapper eventWrapper').fcExternalEvents({ key: value, key: value, key: value })
      (default shown)
      calendar'#calendar'This selector string should point to a fullCalendar object. After fullCalendar renders a calendar, it adds an '.fc' class, but this doesn't target specific calendars, so please use a unique ID for this value if you have more than one calendar per page.
      newEventObject'span.title'In the HTML above, the external event list is added as an unordered list. Using this option allows you to target each event using this selector, but the way the script is set up, it should have at least three levels (main wrapper > event wrapper > newEventObject) or (#eventsToAdd > li > span.title)
      workDayStart'8a'I tried to account for just about any time format (8, 8a, 8am, 8 a.m., 0800, 08:00). But this time is basically the default event start time if no start time is set.
      workDatEnd'4pm'As with the workDayStart, I tried to account for different time formats (it may not be 100% perfect). This time sets the default event stop time if no end time is set.
      draggableOptions{ revert: true }By default, the draggable element will revert to the starting position. Use this option to add or remove any of the draggable options.
      useMetaDatatrueThe script detects the metadata plugin. It will use the metadata it finds if this option is set to true.
      metaDataOptions{}If you do have metadata you want to use, it will by default look in the "newEventObject" class attribute. Adjust these metadata options if it is located elsewhere.
      editExternalEventtrueIf you don't want users to edit the list of external events, set this option to false
      addExternalEventtrueAllows users to add additional external events. They will automatically be able to edit these newly added events even if the "editExternalEvent" option is false.
      disableConfirmfalseDisables the confirmation to delete an external event
    Bugs / Suggestions
    • You will only be able to move external events into the Full Calendar month view. The reason is this script targets the rendered month calendar cells. I don't really plan on making this plugin work in other views as hopefully the author of FullCalendar will include these options in future versions making this script obsolete.
    • To make suggestions or report any bugs please email me at wowmotty at g mail dot com. Thanks!