Showing posts with label jQuery. Show all posts
Showing posts with label jQuery. Show all posts

Friday, December 30, 2011

Adding the MovingBoxes plugin to Blogger

These instructions will allow you to add a MovingBoxes widget to any Blogger post. These instruction really apply to any plugin out there, but instead of making a generic post, I think a specific example is best.

  • picture

    Olivia News Heading

    A very short exerpt goes here... more
  • picture

    Alice News Heading

    A very short exerpt goes here... more and a whole lot more text goes here, so we can see the height adjust.
  • picture

    Yin News Heading

    A very short exerpt goes here... more
  • picture

    Gerri News Heading

    A very short exerpt goes here... more
  • picture

    Tabitha News Heading

    A very short exerpt goes here... more
  • picture

    Mary News Heading

    A very short exerpt goes here... more
  • picture

    Kitty News Heading

    A very short exerpt goes here... more

Note: In the next version of MovingBoxes, I plan to change the width and panelWidth options. At that time, I will update this post.

Code, CSS and image setup

Required Files
I don't know how github would feel about directly linking to their servers. Most businesses frown upon hot-linking and will most likely block your URL, or the entire domain if the hot-linking gets too rampant. So I'd recommend copying each file below and saving it to your own server.
Note that inside of the css, you'll need to change the arrows.png url to point to the new location of the image file.

/*** Left & Right Navigation Arrows ***/
a.mb-scrollButtons {
  background: transparent url(../images/arrows.png) no-repeat;
}

If you don't have a server, you can use dropbox or your iCloud (I don't own a Mac, so I'm only guessing that it'll allow you to save javascript & css files). If you don't have a server to save the files, then first, save the image to an image hosting site, like photobucket, Flickr or something. Then you can save the javascript and css into your own blog design. The main problem with saving into your page design is that it will increase your page size and possibly make the page loading take longer. Either way you'll need to add a gadget, or add to an already existing one.

Add a Gadget
So once you have your files saved and the css file updated:
  • Go to your Dashboard > Design > Add a Gadget > Pick the "HTML/Javascript" gadget.
  • Once the popup window opens, add the following plugin css and javascript in the content window, the URL should point to your hosted files
  • Note: After testing this, it seems that adding a <link> tag inside of the HTML/Javascript gadget gets removed. I'm not sure why, but in this case we can just paste in the entire css.

    <style>
    /*** Overall MovingBoxes Slider ***/
    .mb-wrapper {
     width: 900px; /* default, this is overridden by script settings */
     min-height: 200px;
     border: 5px solid #ccc;
     margin: 0 auto;
     position: relative;
     left: 0;
     top: 0;
     border-radius: 1em;
     -moz-border-radius: 1em;
     -webkit-border-radius: 1em;
     box-shadow: inset 0 0 10px #888;
     -moz-box-shadow: inset 0 0 10px #888;
     -webkit-box-shadow: inset 0 0 10px #888;
    }
    
    /* Panel Wrapper */
    .mb-slider, .mb-scroll {
     width: 100%;
     height: 100%;
     overflow: hidden;
     margin: 0 auto;
     padding: 0;
     position: relative;
     left: 0;
     top: 0;
    
     /***(>'-')> Control Panel Font size here <('-'<)***/
     font-size: 18px;
    }
    
    /* active slider border highlight */
    .mb-active-slider {
     border-color: #999bff;
    }
    
    /*** Slider panel ***/
    .mb-slider .mb-panel {
     width: 350px;  /* default, this is overridden by script settings */
     margin: 5px 0;
     padding: 5px;
     display: block;
     cursor: pointer;
     float: left;
     list-style: none;
    }
    
    /* Cursor to arrow over current panel, pointer for all others,
    change .current class name using plugin option, currentPanel : 'current' */
    .mb-slider .mb-panel.current {
     cursor: auto;
    }
    
    /*** Inside the panel ***/
    .mb-inside {
     padding: 10px;
     border: 1px solid #999;
    }
    
    .mb-inside * {
     max-width: 100%;
    }
    
    /*** Left & Right Navigation Arrows ***/
    a.mb-scrollButtons {
     display: block;
     width: 45px;
     height: 58px;
     background: transparent url(http://css-tricks.github.com/MovingBoxes/images/arrows.png) no-repeat;
     position: absolute;
     top: 50%;
     margin-top: -29px; /* if you change the arrow images, you may have to adjust this (1/2 height of arrow image) */
     cursor: pointer;
     text-decoration: none;
     outline: 0;
     border: 0;
    }
    a.mb-scrollButtons.mb-left {
     background-position: left top;
     left: -45px;
    }
    a.mb-scrollButtons.mb-right {
     background-position: right top;
     right: -45px;
    }
    a.mb-scrollButtons.mb-left:hover {
     background-position: left bottom;
    }
    a.mb-scrollButtons.mb-right:hover {
     background-position: right bottom;
    }
    a.mb-scrollButtons.disabled {
     display: none;
    }
    
    /*** Controls added below the panels ***/
    .mb-controls {
     margin: 0 auto;
     text-align: center;
     background: #ccc;
     position: relative;
     z-index: 100;
    }
    .mb-controls a {
     color: #444;
     font: 12px Georgia, Serif;
     display: inline-block;
     text-decoration: none;
     padding: 2px;
     height: 18px;
     margin: 0 5px 0 0;
     text-align: center;
     outline: 0;
    }
    .mb-controls a.current, .mb-controls a:hover {
     color: #fff;
    }
    .mb-active-slider .mb-controls {
     background: #999bff;
    }
    </style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
    <script src="http://css-tricks.github.com/MovingBoxes/js/jquery.movingboxes.min.js"></script>
    <script>
    jQuery(function(){
    
      jQuery('.movingboxes').movingBoxes({
        startPanel   : 1,      // start with this panel
        width        : 300,    // overall width of movingBoxes
        panelWidth   : 0.5,    // current panel width adjusted to 50% of overall width
        wrap         : false,  // if true, the panel will "wrap" (it really rewinds/fast forwards) at the ends
        buildNav     : true,   // if true, navigation links will be added
        navFormatter : function(){ return "&#9679;"; } // function which returns the navigation text for each panel
      });
    
    });
    </script>

  • Modify the "width" and "panelWidth" options (in red) as desired. Or add and/or remove options following these instructions.
  • If you don't have your own server, then you can open the movingboxes.css file in a text editor and save it into the content window; again make sure the arrow.png url is pointing to the new location in the css below.

    <style>
      /* add movingboxes.css contents here */
    </style>
    <script>
      /* add jquery.movingboxes.min.js contents here */
    </script>
Adding a blog post

Now the first step here would be to open a new post.

Switch the editor to "Edit HTML" - tab in the upper right corner, then paste in the basic plugin HTML Note, keep the <img> and <li> on the same line or blogger will add a <br> in between.

<ul class="movingboxes">
  <li><img src="http://css-tricks.github.com/MovingBoxes/demo/1.jpg" alt="picture">
    <h2>Olivia News Heading</h2>
    <p>A very short exerpt goes here... <a href="http://flickr.com/photos/justbcuz/112479862/">more</a></p>
  </li>
  <li><img src="http://css-tricks.github.com/MovingBoxes/demo/2.jpg" alt="picture">
    <h2>Alice News Heading</h2>
    <p>A very short exerpt goes here... <a href="http://flickr.com/photos/joshuacraig/2698975899/">more</a> and a whole lot more text goes here, so we can see the height adjust.</p>
  </li>
  <li><img src="http://css-tricks.github.com/MovingBoxes/demo/3.jpg" alt="picture">
    <h2>Yin News Heading</h2>
    <p>A very short exerpt goes here... <a href="http://flickr.com/photos/ruudvanleeuwen/468309897/">more</a></p>
  </li>
  <li><img src="http://css-tricks.github.com/MovingBoxes/demo/4.jpg" alt="picture">
    <h2>Gerri News Heading</h2>
    <p>A very short exerpt goes here... <a href="http://flickr.com/photos/emikohime/294092478/">more</a></p>
  </li>
  <li><img src="http://css-tricks.github.com/MovingBoxes/demo/5.jpg" alt="picture">
    <h2>Tabitha News Heading</h2>
    <p>A very short exerpt goes here... <a href="http://www.flickr.com/photos/fensterbme/499006584/">more</a></p>
  </li>
  <li><img src="http://css-tricks.github.com/MovingBoxes/demo/6.jpg" alt="picture">
    <h2>Mary News Heading</h2>
    <p>A very short exerpt goes here... <a href="#">more</a></p>
  </li>
  <li><img src="http://css-tricks.github.com/MovingBoxes/demo/7.jpg" alt="picture">
    <h2>Kitty News Heading</h2>
    <p>A very short exerpt goes here... <a href="#">more</a></p>
  </li>
</ul>

Note that the UL has a class named "movingboxes", it originally had an ID, but to make this plugin work on any future blog entries we need to make sure it's a class name we can remember.

Now, just publish your post and reload your page. The MovingBoxes plugin should initialize and look like it does at the top of this post :)

Saturday, December 17, 2011

All Images Loaded (imagesLoaded)

*NOTE* this code causes infinite loops in IE with image load errors, so I improved and turned this into a real plugin and hosted it on github.


A little jQuery function that checks if all images are loaded. If they all are, the callback function is called. Check out the latest version in this gist.

Script below:
/*
 Check if all images are loaded
 - Callback occurs when all images are loaded
 - image load errors are ignored (complete will be true)
 - Use:
   $('.wrap img').imagesLoaded(function(){
     alert('all images loaded');
   });
*/

jQuery.fn.extend({
  imagesLoaded: function( callback ) {
    var i, c = true, t = this, l = t.length;
    for ( i = 0; i < l; i++ ) {
      if (this[i].tagName === "IMG") {
        c = (c && this[i].complete && this[i].height !== 0);
      }
    }
    if (c) {
      if (typeof callback === "function") { callback(); }
    } else {
      setTimeout(function(){
        jQuery(t).imagesLoaded( callback );
      }, 200);
    }
  }
});

Use it as follows:
$(function(){
  $('.wrap img').imagesLoaded(function(){
    alert('all images loaded');
  });
});

Tuesday, December 6, 2011

jQuery Pathslider

I just created this plugin that is a very basic UI Slider (similar to the jQuery slider), but it doesn't just allow you to move the handle horizontally and vertically, it will follow any shaped curve! If you've ever used Adobe Illustrator or CorelDraw then you probably recognize the Bezier curve below.

The handle, or grip as I call it, can be dragged along the black curve. For now, it only returns values from 0 (green dot) to 100 (red dot).


The plugin is in the early stages of development and still needs a lot of work, but it is usable now.

Check out the demo page, and the builder page. If you would like to help me out, submit an enhancement or issue, or fork a copy of the plugin on Github and send me a pull request! I'd love the input!

Monday, November 14, 2011

jQuery UI Side Scroller with buttons

Once again, I got up at 2:30am wide awake... that's what happens when I fall asleep at 9:30 LOL. Anyway, I was bored so I searched for something to do. I found a question on CSS Tricks asking how to add buttons to the jQuery UI Slider. So starting with the side scroll demo as a base, I put together this demo. That is all :P

Thursday, October 20, 2011

jQuery Rename Attribute (renameAttr)

I woke up this morning with a very unusual urge to make a rename attribute function for jQuery. I know, right.. that's just too weird! So after messing around with it, I decided that it needed to update the data as well. Here is the code I ended up with:

jQuery.fn.extend({
  renameAttr: function( name, newName, removeData ) {
    var val;
    return this.each(function() {
      val = jQuery.attr( this, name );
      jQuery.attr( this, newName, val );
      jQuery.removeAttr( this, name );
      // remove original data
      if (removeData !== false){
        jQuery.removeData( this, name.replace('data-','') );
      }
    });
  }
});

Use it as follows:
// $(selector).renameAttr(original-attr, new-attr, removeData);

// removeData flag is true by default
$('#test').renameAttr('data-test', 'data-new' );

// removeData flag set to false will not remove the
// .data("test") value
$('#test').renameAttr('data-test', 'data-new', false );

Basically, it adds a new attribute with the same value and removes the old one. It automatically removes the jQuery data for the original attribute unless you set the "removeData" flag to false. Check out this demo

Thursday, October 6, 2011

Adding Swipe Support

I spent some time trying to figure out how to add mobile swipe support without using jQuery Mobile, because the swipe is all I really needed. I don't own an iPhone/iPad/iAnything, so it took a bit of back-and-forth testing - thanks to all the folks over at CSS-Tricks.com - to get this to finally work.



Here is the complete code:

var maxTime = 1000, // allow movement if < 1000 ms (1 sec)
    maxDistance = 50,  // swipe movement of 50 pixels triggers the swipe

    target = $('#box'),
    startX = 0,
    startTime = 0,
    touch = "ontouchend" in document,
    startEvent = (touch) ? 'touchstart' : 'mousedown',
    moveEvent = (touch) ? 'touchmove' : 'mousemove',
    endEvent = (touch) ? 'touchend' : 'mouseup';

target
    .bind(startEvent, function(e){
        // prevent image drag (Firefox)
        e.preventDefault();
        startTime = e.timeStamp;
        startX = e.originalEvent.touches ? e.originalEvent.touches[0].pageX : e.pageX;
    })
    .bind(endEvent, function(e){
        startTime = 0;
        startX = 0;
    })
    .bind(moveEvent, function(e){
        e.preventDefault();
        var currentX = e.originalEvent.touches ? e.originalEvent.touches[0].pageX : e.pageX,
            currentDistance = (startX === 0) ? 0 : Math.abs(currentX - startX),
            // allow if movement < 1 sec
            currentTime = e.timeStamp;
        if (startTime !== 0 && currentTime - startTime < maxTime && currentDistance > maxDistance) {
            if (currentX < startX) {
                // swipe left code here
                target.find('h1').html('Swipe Left').fadeIn();
                setTimeout(function(){
                    target.find('h1').fadeOut();
                }, 1000);
            }
            if (currentX > startX) {
                // swipe right code here
                target.find('h1').html('Swipe Right').fadeIn();
                setTimeout(function(){
                    target.find('h1').fadeOut();
                }, 1000);
            }
            startTime = 0;
            startX = 0;
        }
    });


Now, lets break down what each line does. First, some definitions:

var maxTime = 1000, // allow movement if < 1000 ms (1 sec)
    maxDistance = 50,  // swipe movement of 50 pixels triggers the swipe

    target = $('#box'),
    startX = 0,
    startTime = 0,

The "maxTime" variable is a set to 1000 milliseconds. It is used to compare the touch start and touch end times, and if less than one second (1000 ms) it is considered to be a valid swipe, otherwise it is ignored. Basically, we don't like them slow swipers! Hehe, ok, actually, it to determine if the event ends up being a touch or a swipe.

"maxDistance" is the number of pixels from the touch start point that the mouse or a finger moved to determine if a swipe or touch is occurring.

The "target" variable, is the target element to add swipe support to. For the demo, I added an H1 tag inside of this element to add a swipe message. The "startX" and "startTime" variables are set to zero because the "touchmove" or "mousemove" event looks to see if they are set with the "startX" position and start time. If zero, it ignores the move.

In the next part we figure out of the device has touch support and set up the event names appropriately:

touch = "ontouchend" in document,
startEvent = (touch) ? 'touchstart' : 'mousedown',
moveEvent = (touch) ? 'touchmove' : 'mousemove',
endEvent = (touch) ? 'touchend' : 'mouseup';

The "touch" varible is true if the "ontouchend" event exists, which means touch is supported. All that line is doing is looking to see if that object exists.

The next variables, "startEvent", "moveEvent" and "endEvent" contain the necessary event names for start, move and end, respectively. Which the next lines of code will now bind to:
target
    .bind(startEvent, function(e){
        // prevent image drag (Firefox)
        e.preventDefault();
        startTime = e.timeStamp;
        startX = e.originalEvent.touches ? e.originalEvent.touches[0].pageX : e.pageX;
    })
The "touchstart" or "mousedown" event code contains the following:

"e.preventDefault()" prevents the image drag function in Firefox which actually makes you think you're dragging the image instead of swiping. Now we define "startTime" and "startX" as the start time and position of the swipe. The "startX" needs to get the position of the touch from the touches variable, but only the first one. We don't want to swipe if there are multiple touches (gestures) but it shouldn't work anyway since we're not binding to the gestures event.
.bind(endEvent, function(e){
    startTime = 0;
    startX = 0;
})
Now the "touchend" or "mouseup" event code only clears the start time and position variables. The reason for this, which was a fun and painful lesson, is that these events don't fire when your mouse/finger leaves the element or goes off the screen. So the actual swipe calculations are done in the move event functions.

.bind(moveEvent, function(e){
    e.preventDefault();
    var currentX = e.originalEvent.touches ? e.originalEvent.touches[0].pageX : e.pageX,
        currentDistance = (startX === 0) ? 0 : Math.abs(currentX - startX),
        // allow if movement < 1 sec
        currentTime = e.timeStamp;
    if (startTime !== 0 && currentTime - startTime < maxTime && currentDistance > maxDistance) {
        if (currentX < startX) {
            // swipe left code here
            target.find('h1').html('Swipe Left').fadeIn();
            setTimeout(function(){
                target.find('h1').fadeOut();
            }, 1000);
        }
        if (currentX > startX) {
            // swipe right code here
            target.find('h1').html('Swipe Right').fadeIn();
            setTimeout(function(){
                target.find('h1').fadeOut();
            }, 1000);
        }
        startTime = 0;
        startX = 0;
    }
});

The "touchmove" or "mousemove" events is where the main portion of this swipe code exists. Again, we want to prevent the default functionality of the move/drag. The "currentX" variable is set with the current x position of the finger/mouse. Again, the x position is obtained from the touches variable, if available. The difference "currentDistance" between the starting x and current x position is then determined. We need the absolute value of this number (ignore the negative sign if it is there) to see if it is more than the "maxDistance" variable. Also here is another trick to make sure the move event is occurring after a start event, check to make sure the starting x position isn't zero. If it is, set the "currentDistance" variable to zero. We also need determine the "currentTime" current time of the move event.

Now, we check to make sure the move event occurred after a start event. This can happen is the start event occurs outside of the element or window. So, first we make sure the "startTime" isn't zero, then we check that the time difference from start to current time is less than one second. And finally, we check that the current distance is more than the max distance setting. If it is, then we have a swipe!

YAY finally a swipe! Now to just figure out if it was going to the right or left. We do this by comparing the current position "currentX" to the starting position "startX"; if the current position is less than the start, then it's a swipe to the left and if it is greater, then the swipe was to the right.

Last but not least, we set the start time and position back to zero to prevent multiple firing of the swipe event.

I hope everything had a clear enough explanation. Please feel free to leave a comment or email me (gmail with wowmotty as the user) with questions or if you need further clarification.

Thursday, September 22, 2011

Print a Paragraph

By default, browsers will print the content of an entire page/web page or selected text. With some simple scripting you can make it easier for your users to get the browser to print the contents of a particular block or paragraph. The trick is to copy these contents into a new popup window, then print the contents of that window. I put together a very simple demo, which I should turn into a plugin, of how to do this:

Wednesday, August 17, 2011

AnythingSlider FX Builder

So, to make it easier to figure out how to add FX to AnythingSlider, I put together a bookmarklet (get it from here) that allows you to build/play with the effects live :)



If you need instructions, I have some very basic information in the readme file on github.

Right now, it's still in beta and it only works on the first slider on the page. I'd appreciate any feedback on what could be improved, changed, or if you find any problems.

Saturday, June 18, 2011

jQuery Tablesorter, The Missing Docs

If you need support for my fork of tablesorter, please contact me here:

The Missing Docs for jQuery Tablesorter 2.0

These docs have been incorporated into my

All Defaults


Appearance
cssHeader: "header"The CSS style used to style the header in its unsorted state.
cssAsc: "headerSortUp"The CSS style used to style the header when sorting ascending.
cssDesc: "headerSortDown"The CSS style used to style the header when sorting descending.
cssChildRow: "expand-child"This allows you to add a child row that is always attached to the parent. See the children rows section below.
widgetZebra: { css: ["even", "odd"] }Set the CSS classes used for zebra striping the table. See the updating zebra striping section below.
widthFixed: falseIndicates if tablesorter should apply fixed widths to the table columns. This is useful for the Pager companion. Requires the jQuery dimension plugin to work. See the main demo page
onRenderHeader: nullThis function is called when classes are added to the th tags. You can use this to append HTML to each header tag. See the Render Header section below.
Sort Options
sortInitialOrder: "asc"A string of the inital sorting order can be "asc" or "desc". This is overridden bt the sortList settings.
sortForce: nullUse to add an additional forced sort that is prepended to sortList. For example, sortForce: [[0,0]] will sort the first column in ascending order. See the main demo page
sortList: []Add an array of the order the table should be initially sorted; e.g. sortList: [[0,1], [1,0]]. The first part "[0,1]" will sort the first column (zero based index) in decending order and the second part "[1,0]" is to sort the second column in ascending order. See the main demo page.
sortAppend: nullUse to add an additional default sorting rule, that is appended to the sortList.
Parsers & Widgets
headers: {}See the Change how you sort a column section below or see the main demo page
textExtraction: "simple"See the Text Extraction section below or see the main demo page
sortLocaleCompare: trueBoolean flag indicating whenever to use String.localeCampare method or not. This is only used when comparing text strings.
parsers: {}Internal list of all of the parsers. See a complete list of parsers below.
widgets: []Initialize widgets using this option (e.g. widgets : ['zebra'], or custom widgets widgets: ['zebra', 'myCustomWidget']; see this demo on how to add a custom widget.)
selectorHeaders: 'thead th'jQuery selectors used to find the header cells. You can change this, but the table will still need the required thead and tbody before this plugin will work properly.
headerList: []Internal list of each header element as selected using jQuery selectors in the selectorHeaders option.
dateFormat: "us"Set the date format. See the dataFormat section below.
Interaction
sortMultiSortKey: "shiftKey"The key used to select more than one column for multi-column sorting. Defaults to the shift key. Other options might be ctrlKey, altKey. See the main demo page
cancelSelection: trueIndicates if tablesorter should disable selection of text in the table header (TH). Makes header behave more like a button.
Unknown
decimal: '/\.|\,/g'Regex to find the decimal "." for U.S. format and "," for European format... but I can't find it being used anywhere in the plugin.
Debugging
debug: falseBoolean flag indicating if tablesorter should display debuging information usefull for development. This displays information in the console, if available, or in alerts. See the main demo page

Update Default Settings

Update any of the default settings above using this format:
$(selector).data("tablesorter").{default name} = newValue;
Here are a few examples:
// Change sortForce
$("table").data("tablesorter").sortForce = [[1,0]];
// it appears that the only way to update the table is to resort it
$("table").trigger("sorton", [[0,1]]);
// Add zebra sorting after the table has initialized
$("table").data("tablesorter").widgets = ["zebra"];
// there is a method to apply widgets!
$("table").trigger("applyWidgets");

Child Rows

To add a row that remains attached to a parent row, add the "expand-child" class to the row.

You can add some scripting to hide these child rows and have them expand when you click on a link; this is the original reason for the css name.

Here is the original mod page, the code was added into the TableSorter core but remains undocumented.

This makes the tablesorter plugin keep these rows together. This css class can be changed using the "cssChildRow" option.

Here is some example markup:
<table width="100%" border="1">
  <thead>
    <tr>
      <th>Item #</th>
      <th>Name</th>
      <th>Available</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>12345</td>
      <td>Toy Car</td>
      <td>5</td>
    </tr>
    <tr class="expand-child"> <!-- this row will remain attached to the above row, and not sort separately -->
      <td colspan="3">
        It's a toy car!
      </td>
    </tr>
    <tr>
      <td>23456</td>
      <td>Toy Plane</td>
      <td>2</td>
    </tr>
    <tr class="expand-child"> <!-- this row will remain attached to the above row, and not sort separately -->
      <td colspan="3">
        It's a toy plane!
      </td>
    </tr>
    <tr class="expand-child"> <!-- this row will remain attached to the above two rows, and not sort separately -->
      <td colspan="3">
        and it flies!
      </td>
    </tr>
  </tbody>
</table>


Update Zebra Striping After Sorting

Actually the zebra striping widget does this for you automatically.

By default the odd and even rows are styled using "odd" and "even" class names ({ css: [ "even", "odd" ] }).

Change these css class names using the widgetZebra option as follows:
$(function(){
  $("table").tablesorter({
    widgets: ["zebra"], // initialize zebra striping of the table
    widgetZebra: { css: [ "normal-row", "alt-row" ] }
  });

Modify the Header Markup

The onRenderHeader option allows you to add a function that which can modify the HTML of each header tag. In the example below, the header cell (th) content is wrapped with a span tag to allow for better styling (source).
$(function(){
  $("table").tablesorter({
    onRenderHeader: function (){
      this.wrapInner('<span class="roundedCorners"></span>');
    }
  });
});
and you'll end up with this (only the thead is shown):
<thead>
  <tr>
    <th class="header"><span class="roundedCorners">Column 1</span></th>
    <th class="header"><span class="roundedCorners">Column 2</span></th>
  </tr>
</thead>


Change how you sort a column

The plugin attempts to detect the type of data that is contained in a column, but if it can't figure it out then it defaults to alphabetical.

You can easily override this by setting the header argument (or column parser).
$(function(){
  $("table").tablesorter({
    headers: {
      0: { sorter: false },      // disable first column
      1: { sorter: "digit" },    // sort second column numerically
      4: { sorter: "shortDate" } // sort the fifth column by date (e.g. mm/dd/yyyy if the date format is "us")
    }
  });
});
*Note* the header number starts with zero (zero based index).

Here is a list of available sorter values/parsers:

sorter: falsedisable sort for this column.
sorter: "text"Sort alphabetically.
sorter: "digit"Sort numerically.
sorter: "currency"Sort by currency value (supports "£$€").
sorter: "ipAddress"Sort by IP Address.
sorter: "url"Sort by url.
sorter: "isoDate"Sort by ISO date (YYYY-MM-DD or YYYY/MM/DD).
sorter: "percent"Sort by percent.
sorter: "usLongDate"Sort by date (U.S. Standard, e.g. Jan 18, 2001 9:12 AM).
sorter: "shortDate"Sort by a shorten date (see "dateFormat").
sorter: "time"Sort by time (23:59 or 12:59 pm).
sorter: "metadata"Sort by the sorter value in the metadata - requires the metadata plugin.

Change the Date Format (dateFormat)

"us""mm-dd-yyyy" or "mm/dd/yyyy"
"uk""dd-mm-yyyy" or "dd/mm/yyyy"
"dd/mm/yy" or
"dd-mm-yy"
Sort by short year (it appears to sort by day first, not the year)




Change the Sorted Columns

There are three options to determine the sort order and this is the order of priority:
  1. sortForce forces the user to have this/these column(s) sorted first (null by default).
  2. SortList is the initial sort order of the columns.
  3. SortAppend is the default sort that is added to the end of the users sort selection (null by default).
The value of these sort options is an array of arrays and can include one or more columns. The format is an array of instructions for per-column sorting and direction in the format: [[columnIndex, sortDirection], ... ] where columnIndex is a zero-based index for your columns left-to-right and sortDirection is 0 for Ascending and 1 for Descending. A valid argument that sorts ascending first by column 1 and then column 2 looks like: [[0,0],[1,0]]
$(function(){
  $("table").tablesorter({
    sortForce  : [[0,0]],        // always sort first column first
    sortList   : [[1,0], [2,0]], // initial sort columns (2nd and 3rd)
    sortAppend : [[3,0]]         // always add this sort on the end (4th column)
  });
});
*NOTE* When writing this post, I didn't realize that the sortAppend option was listed as an option, but the code for it did not exist. This problem is fixed in my fork of tablesorter (example).

Text Extraction

This is demonstrated in the Dealing with markup inside cells demo page, but the example uses vanilla javascript to find the desired text, like this:
$(function(){
  $("table").tablesorter({
    textExtraction: function(node) {
      return node.childNodes[0].childNodes[0].innerHTML;
    }
  });
});
But you could make your life easier and just make the node into a jQuery object and then "find" what you need:
$(function(){
  $("table").tablesorter({
    textExtraction: function(node) {
      return $(node).find("span:last").text();
    }
  });
});
Now if the text you are finding in the script above is say a number, then just include the headers sorter option to specify how to sort it. Also in this example, we will specify that the special textExtraction code is only needed for the second column ("1" because we are using a zero-based index). All other columns will ignore this textExtraction function.


*NOTE* When writing this post, I didn't realize that the textExtraction option did not allow defining it per column, as shown below, but this has been fixed in the forked github version - example.
$(function(){
  $("table").tablesorter({
    textExtraction: {
      1: function(node) {
           return $(node).find("span:last").text();
      }
    },
    headers: {
      1: { sorter : "digit" }
    }
  });
});


Methods

See examples of each further down
sortonResort the table using new sort parameters.
updateUpdate the stored tablesorter data and the table.
appendCacheUpdate a table that has had its data dynamically updated; used in conjunction with "update"
updateCellUpdate a table cell in the tablesorter data.
applyWidgetIdApply a widget (wrapped in square brackets) to the table one time only.
applyWidgetsApply previously selected widgets to the table - will update the widget with new sort.

Resort the table - "sorton" method

See the full example in the tablesorter docs: Sort table using a link outside the table
// Choose a new sort order
var sort = [[0,0],[2,0]];
// Note that the sort value below is inside of another array (inside another set of square brackets)
$("table").trigger("sorton", [sort]);

Update the Table

See the full example in the tablesorter docs: Appending table data with ajax
// Add new content
$("table tbody").append(html);
// let the plugin know that we made a update
$("table").trigger("update");
// set sorting column and direction, this will sort on the first and third column
var sorting = [[2,1],[0,0]];
// sort on the first column
$("table").trigger("sorton", [sorting]);

Append Cache

If you dynamically change the table content, more than just one cell like in the "updateCell" example above, you may possibly have to trigger two events: "update" and "appendCache".

This answer is from a StackOverflow answer
// Table data was just dynamically updated
$(table)
  .trigger("update")
  .trigger("appendCache");

Update a Table Cell

Example from these alternate tablesorter docs: Updating the table cache - the demo doesn't work, but I've tested the example code below and it works properly.
$(function() {
  $("table").tablesorter();
  $("td.discount").click(function(){
      // randomize a number
      var discount = '$' + Math.round(Math.random() * Math.random() * 100) + '.' + ('0' + Math.round(Math.random() * Math.random() * 100)).slice(-2);
      $(this).text(discount);
      // update the table, so the tablesorter plugin knows its value
      $("table").trigger("updateCell",[this]);
      // set sorting column and direction, this will sort on the first and third column
      var sorting = [[3,1]];
      // sort on the first column
      $("table").trigger("sorton",[sorting]);
      return false;
  });
});
<table class="tablesorter" cellspacing="1">
  <thead>>
    <tr>
      <th>first name</th>
      <th>last name</th>
      <th>age</th>
      <th>total</th>
      <th>discount</th>
      <th>date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>peter</td>
      <td>parker</td>
      <td>28</td>
      <td class="discount">$9.99</td>
      <td>20%</td>
      <td>jul 6, 2006 8:14 am</td>
    </tr>
    <tr>
      <td>john</td>
      <td>hood</td>
      <td>33</td>
      <td class="discount">$19.99</td>
      <td>25%</td>
      <td>dec 10, 2002 5:14 am</td>
    </tr>
    <tr>
      <td>clark</td>
      <td>kent</td>
      <td>18</td>
      <td class="discount">$15.89</td>
      <td>44%</td>
      <td>jan 12, 2003 11:14 am</td>
    </tr>
    <tr>
      <td>bruce</td>
      <td>almighty</td>
      <td>45</td>
      <td class="discount">$153.19</td>
      <td>44%</td>
      <td>jan 18, 2001 9:12 am</td>
    </tr>
    <tr>
      <td>bruce</td>
      <td>evans</td>
      <td>22</td>
      <td class="discount">$13.19</td>
      <td>11%</td>
      <td>jan 18, 2007 9:12 am</td>
    </tr>
  </tbody>
</table>

Apply a New Widget "applyWidgetId"

Apply a widget to the table. In this example, we apply the zebra striping to the table after it has been initialized.
$(function(){
  // initialize tablesorter without the widget
  $("table").tablesorter();
  
  // click a button to apply the zebra striping
  $("button").click(function(){
    $('table').trigger('applyWidgetId', ['zebra']);
});

Apply Chosen Widgets "applyWidgets"

Reapply a widget to the table. In this example, we apply the zebra striping to the table after it has been initialized.

This is basically an alternate method to the "applyWidgetId", but in the example below you can add or remove widgets from the chosen list.
// Update the list of widgets to apply to the table (add or remove)
$("table").data("tablesorter").widgets = ["zebra"];
$("table").trigger('applyWidgets');




Triggered Events

sortStartThis event fires when the tablesorter plugin is about to start resorting the table.
sortEndThis event fires when the tablesorter plugin has completed resorting the table.


Bind to the "sortStart" and/or the "sortEnd" events as shown on the example page
$(function(){
  // initialize the tablesorter plugin
  $("table").tablesorter();
  // bind to sort events
  $("table")
    .bind("sortStart",function() {
      $("#overlay").show();
    })
    .bind("sortEnd",function() {
      $("#overlay").hide();
    });
});
Or here is another example from StackOverflow
$(function(){
  $("table")
    .tablesorter()  
    .bind("sortEnd", function(){  
      $("table tr").removeClass("block");
      // adds the "block" class to every 8th row
      $("table tr:nth-child(8)").addClass("block");
    });
});

Monday, June 6, 2011

Equalizer

This script was first written by Stephen Akins to equalize column heights in multiple rows. Chris Coyier of CSS Tricks then posted an update which allowed the heights to adjust while resizing a page. I simply debugged, added a few improvements (like minimum and maximum height, an idea from Mike Avello's plugin) and turned it into a plugin.


In the screen shot above, there are three blocks containing three columns. The three blocks have identical HTML. The left block is unmodified. The center block has Equalizer applied with a max height setting; and each block that exceeds the max height has a css class applied which sets the overflow to auto and adds the different background color for the demo, but you can do whatever you want via the css. And the right block has Equalizer applied with a minimum height setting; you should be able to see in the screen shot that the middle row of the right block has a minimum height set.

Try out the demo, resize your browser window and see how everything changes.

Monday, May 2, 2011

FancySelector

I just created FancySelector which replaces the standard select with a more visually appealing select. It allows you to scroll through the options with either the keyboard or mouse. Selecting multiple options is similar but not exactly the same as using a standard select. Please see the documentation for more details.

There are two demos, a full screen demo (pictured below) and an inline selector demo.


This jQuery plugin is available for download on github.

Saturday, April 23, 2011

Visual Event Bookmarklet

I've been using Visual Event bookmarklet to help quickly visualize which events are attached to a page while troubleshooting problems.

I do have one problem with the script. It adds too many layers so you can't get to the lower layers. Here is a screen shot of how the last post I made looks with Visual Event (on the left) and the second screen shot is how it looks after the script is applied (on the right):

I made a github gist and a jsFiddle demo of this script. To use it, just add the following script into the Firebug console to enable the script:
var veColors = [ 'black', 'orange', 'purple', 'green', 'blue', 'yellow', 'red' ],
 veColorLength= veColors.length - 1,
 veLayerIndex = 0;
 
function showVeLayer(nxt){
 veLayerIndex += (nxt) ? 1 : -1;
 if (veLayerIndex > veColorLength) { veLayerIndex = 0; }
 if (veLayerIndex < 0) { veLayerIndex = veColorLength; }

 var veLayer =  $('.Event_bg_' + veColors[veLayerIndex]);
 if (veLayer.length === 0 ) { showVeLayer(nxt); return; }

 $('.Event_bg_' + veColors.join(', .Event_bg_')).hide();
 veLayer.show();
};

$(document).keyup(function(e){
 switch(e.which){
  case 39: case 40: // right/down
   showVeLayer(true);
   break;
  case 37: case 38: // left/up
   showVeLayer();
   break;
 }
});

FullCalendar mini-sized

I've always liked Adam Shaw's FullCalendar plugin and while I was trolling Stackoverflow I found a question about how one would make a tiny version of the calendar. Gears started grinding and I figured that it could be done with just some basic CSS. YAY!!

This is from the answer I posted on Stackoverflow:
You can make a fully functional tiny version by adding a bit of CSS. I had to add a "eventMouseover" callback to add the event name to the title attribute, so you can see it's name in the tooltip.

Here is a screen shot of the mini-sized calendar (200 x 225)


And jsFiddle for a demo:



So, just in case something happens to Stackoverflow and/or jsFiddle, here is the CSS and javascript that was used:
#calendar {
    width: 200px;
    margin: 0 auto;
    font-size: 10px;
}
.fc-header-title h2 {
    font-size: .9em;
    white-space: normal !important;
}
.fc-view-month .fc-event, .fc-view-agendaWeek .fc-event {
    font-size: 0;
    overflow: hidden;
    height: 2px;
}
.fc-view-agendaWeek .fc-event-vert {
    font-size: 0;
    overflow: hidden;
    width: 2px !important;
}
.fc-agenda-axis {
    width: 20px !important;
    font-size: .7em;
}

.fc-button-content {
    padding: 0;
}
$(document).ready(function() {

    $('#calendar').fullCalendar({
        theme: true,
        header: {
            left: 'prev,next today',
            center: 'title',
            right: 'month,agendaWeek,agendaDay'
        },
        editable: true,

        // add event name to title attribute on mouseover
        eventMouseover: function(event, jsEvent, view) {
            if (view.name !== 'agendaDay') {
                $(jsEvent.target).attr('title', event.title);
            }
        }
    });

});

Tuesday, April 19, 2011

Vertical Parallax Effect for the Entire Page

I found a game site (Elder Scrolls) that has a really cool vertical scrolling effect that I wanted to duplicate, but it only works in webkit browsers. I didn't make it into a plugin, but instead made this tutorial, because if you understand the basics, you can add more background images or use CSS3 to add multiple background images.



This is a screen shot of the web page while it is at the top. Note the location of the building tower top is near the top of the logo that is under "Generic".


This screen shot shows how the top of "Box 1" is now above the building tower. Blocks in the foreground move slightly faster than the background image.


Here is the final demo of the vertical scrolling effect (see it as a full page).

How it's done

The Images
This effect uses two background images. The top image (bg1.jpg, 1920x1080 pixels) fades to solid black on its bottom edge.

It's made to be a bit blurry, but you can duplicate the game site's background image by keeping the foreground sharp and the background blurry... it's a cooler effect ;)
 

The second background image (bgtile.jpg, 963x1641 pixels) is added as a background image that appears under the above top image. The css is adjusted so that the top of this image appears below the top image so that you don't see a straight black line cut through the top.

This image is blurry and mostly black, it fades to solid black at the edges, with a rock-like texture. It makes the vertical parallax scroll very subtle, so you may want to adjust it as desired.


The other two images that are used are the title/logo image (title.png, 400x300 pixels).



And the box background (bg-black-55.png, 20x20 pixels) which is a png file of solid black with a 55% opacity.


The Markup
This is very basic HTML markup. The body contains the repeating background tile image (bgtile.jpg). A wrapper is immediately inside the body which contains the top background image (bg1.jpg). These two images could be combined in the body tag if you use css3; then you could use the wrapper for additional images. The Header contains the logo (title.png) and each block of content has the box background image (bg-black-55.png) applied. Fill in the "div.content" block with whatever you want.
<body> <!-- contains repeated background image -->
<div id="wrapper"> <!-- contains top image -->

<div id="header"></div> <!-- contains the page title image -->

 <div class="block"> <!-- contains 55% opacity background image -->
  <h3>Block 1</h3>
  <div class="content">Content 1.</div>
 </div>

 <div class="block"> <!-- contains 55% opacity background image -->
  <h3>Block 2</h3>
  <div class="content">Content 2.</div>
 </div>

 <div class="block"> <!-- contains 55% opacity background image -->
  <h3>Block 3</h3>
  <div class="content">Content 3.</div>
 </div>

 <div class="block"> <!-- contains 55% opacity background image -->
  <h3>Block 4</h3>
  <div class="content">Content 4.</div>
 </div>

 <div class="block"> <!-- contains 55% opacity background image -->
  <h3>Block 5</h3>
  <div class="content">Content 5.</div>
 </div>

</div>

</body>

The CSS
The CSS below doesn't have a lot of comments, but the important parts to focus on are the main background image positions.
body {background: #333; color: #ddd;}
a:link { color: #ddd; }
a:hover { text-decoration: underline; }
a:visited,a:active { color: #999; }

/* Tiled background image */
body {
 margin: 0;
 padding: 0;
 /* Use height of header image for top position */
 background: #000 url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7fBBufKSR47RD9ESntGl85BAeIpSrYvQv9JzbnrK6i-jYhidex39OZ6_4lDD3EXxKv7I3pd4XWnOUyzax9evROh_GLcIfkX8I3vQO6Y1FuA0KruXm33MggzrqsSVR91iOFJvTZylHFiM/s200/bgtile.jpg) left 1080px repeat-y;
}
/* Top background image (1920x1200) */
#wrapper {
 position: relative;
 top: 0;
 left: 0;
 height: 100%;
 width: 100%;
 background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizCx7mqIPhdQ10Xgmieaa4PTAR5suXGEi7ezqiiL5G_h0yFCXhvibhec2mTLDBXGnkTbWC-LeqbKT634Ppt40wdciHfm6fq7QuY5v1pDeWJ6nvzv8T7bj3mrOBd-oxDGuhJmIc5daHeA0/s200/bg1.jpg) center top repeat-x;
 z-index: 100;
}
/* Page Title image */
#header {
 height: 350px;
 background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipx4m-HiIJ90H0QrnLtd5DHyP1J29su3Sn1McbkRcQrKu934Z6WjSGM7stMU5RB97-ZVrQ4_zHV7r81NuIXWmTdXIkoNyuTCj19sGjfxGDkLfOpL0Ou_1jE4xWB-NS5WnP_svT4OkqhbQ/s200/title.png) center 40px no-repeat;
}
/* Content Block with 55% opacity background image */
.block {
 width: 400px;
 height: 500px;
 margin: 20px auto;
 border: #333 1px solid;
 padding: 20px;
 background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj82Brf2wM1QpoBT96gFD5ZXiJFpFTBHxKF4ghGPJwMMkkSF_ifPi4PMFM20c5ravbOTe1lhOLzrK0TDmV0Vq_wys_x09oF3VTSPh_sOrup0B5xc7CRR3tqh9zHm3DvQRIL2maSeryZ2us/s1600/bg-black-55.png);
}
.block h3 {
 font-family: 'Arial Black', Gadget, sans-serif;
 font-size: 130%;
}

The Script
jQuery(document).ready(function(){
  // saved values
  var st, 
   // get window and body elements
   win = jQuery(window)[0],
   body = jQuery('body')[0],
   wrap = jQuery('#wrapper')[0],
   // make sure we target the correct document (in IE)
   doc = (jQuery.support.boxModel) ? document.documentElement : document.body,
  
   // Set top background image height here, in pixels
   imgH = 1080;

  // vertical parallax scroll code
  jQuery(win).scroll(function(){
   // get the page scroll top (IE uses doc.scrollTop)
   st = (win.pageYOffset || doc.scrollTop );

   // Limit moving top image (in the "wrap") only when in view (st < imgH)
   // Doing this reduces the amount of DOM activity so it doesn't slow down the scrolling.
   // Here is where the background position of the top image is moved by 1/4 (st/4) of the total amount scrolled
   // Increasing the fraction (making it closer to one) will speed up the background parallax scroll
   // Decreasing the fraction will slow down the parallax scroll
   if (st < imgH) { wrap.style.backgroundPosition = 'center ' + (st/4) + 'px'; }

   // This line limits the tiled background image in the "body"
   body.style.backgroundPosition = 'left ' + ( imgH + st/4) + 'px';
  });
});
Code breakdown
  • The first and last line wrap the code which is run when the document is ready. This is a jQuery method and can be written several different ways. Basically, any code inside is run when the basic structure and code of the page has completed loading. Images may or may not have completed loading at this time.
    jQuery(document).ready(function(){
      // code to run
    });
  • The next few lines save the variables that are repeatedly used in the script. Saving them reduces the amount of time taken to run code inside the scroll function. See the optimization section for more details.
    // saved values
    var st, 
     // get window and body elements
     win = jQuery(window)[0],
     body = jQuery('body')[0],
     wrap = jQuery('#wrapper')[0],
     // make sure we target the correct document (in IE)
     doc = (jQuery.support.boxModel) ? document.documentElement : document.body,
    
    *Note that each line ends with a comma - it is defining multiple variables with one "var".

  • The next saved variable saves the top background image height (bg1.jpg). This is needed so the script can figure out where to start the tiling of the repeated background image (bgtile.jpg). This ensures that the tiled background image isn't overlapped by the top background image making the user see a sharp black edge at the overlap. The script also uses this height to stop the parallax scroll of the top background image when it isn't in view. The reason for this is discussed in the optimization section below.
    // Set top background image height here, in pixels
    imgH = 1080;
  • Now we bind to the window scroll event. This event is fired everytime the browser window is scrolled. So it can be called hundreds of times while scrolling down the page. This is the reason the code inside this function is kept as minimal as possible.
    // vertical parallax scroll code
    jQuery(win).scroll(function(){
    
      // code run each time the page is scrolled
    
    }); // second to last line in the completed script
  • Get the scroll top of the page. Check standard browsers variable, and if not defined (IE) then get the document scroll top.
    // get the page scroll top (IE uses doc.scrollTop)
    st = (win.pageYOffset || doc.scrollTop );
  • Apply the parallax to the top background image. 
    // Here is where the background position of the top image is moved by 1/4 (st/4) of the total amount scrolled
    // Increasing the fraction (making it closer to one) will speed up the background parallax scroll
    // Decreasing the fraction will slow down the parallax scroll
    if (st < imgH) { wrap.style.backgroundPosition = 'center ' + (st/4) + 'px'; }
    • The first thing we do is check if the scroll top (st) is less than the top background image height. If it is, then use parallax on the top background image.
    • "wrap" is one of our saved variables that points to the page wrapper. Here we set the background position using direct DOM manipulation. See optimization section for more details.
    • The background position has two parts - "X Y" positions. We care centering the image from left to right (the X-position), then taking one fourth (1/4) of the scroll top position and making that the background's Y-position. This is basically how the parallax scroll works. It scroll 1/4 less than the actual page. If you add another layer (say wrapper 2), it should be scrolled slightly more (a number closer to one, like 2/3).
    • So here the top background image is scrolled 1/4 less (1/4 * st) than the page itself. Make this number closer to one (i.e. 3/4 * st) to make the scroll more like the page scroll. Or make the number further from one (i.e. 1/8 * st) to make the scroll a tiny bit. Making the number too small may make the background image appear fixed, so don't go too crazy ;)
  • Apply the parallax to the tiled background image.
    // This line limits the tiled background image in the "body"
    body.style.backgroundPosition = 'left ' + ( imgH + st/4) + 'px';
    • Now we are applying the background position to the body of the page, where the tiled background image (bgtile.jpg) is seen.
    • Here we are place the background image on the left edge (centering should be fine too) and again 1/4 of the scroll top of the page. In addition we add the top image height (imgH) to keep the tiled background image aligned to the bottom of the top background image. So we make sure not to see that black image edge.
    • Since the body background image is behind the wrapper background image, you could make this parallax scroll even slower to give more of a feel of it being further off in the distance. This would look especially good with multiple background images available when using css3.
Optimizations
  • This script was optimized so that a minimal amount of code is run inside the scroll function.
  • This ensures that the code doesn't slow down the page scroll, because the scroll function is called constantly. It's probably not a big deal is modern browsers, but is very noticeable in older browsers. 
  • This was done, in part, by saving variables. This limits the amount of look ups that need to be done by the script. Using $(window) or $(document) needs to call several functions to get a value, so saving it in a variable saves time.
  • To set the background position, the script sets the background position directly in the DOM. Again, this was done to minimize function calls. I didn't have any trouble with cross browser compatibility in any browsers, including Opera and IE7+.

    Tuesday, December 21, 2010

    Keycaster

    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

    SqueezeBox

    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.

    Features:
    • 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

    AnythingSlider

    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.