Interactive Physics Animations Javascript Canvas 03

This iteration really isn’t that big, but I figured baby steps may be the way to go here. We’re just giving the first circle a random position. The other dots are positioned relative to the first one still. interactive physics animations via javascript & canvas | 03.

[cc lang=”javascript”]
$(function () {
var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

canvas = $(“#canvas”)[0];
context = canvas.getContext(“2d”);
width = canvas.width;
height = canvas.height;
x = Math.random()*canvas.width/5;
y = Math.random()*canvas.height/5;
draw();

$(“#canvas”).mousedown(function (event) {
var dx, dy, dist;
dx = event.pageX – this.offsetLeft – x;
dy = event.pageY – this.offsetTop – y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) { drag = true; clickX = dx; clickY = dy; } else { drag = false; } }); $("#canvas").mouseup(function (event) { drag = false; }); $("#canvas").mousemove(function (event) { if(drag) { x = event.pageX - this.offsetLeft - clickX; y = event.pageY - this.offsetTop - clickY; draw(); } }); function draw() { context.clearRect(0, 0, width, height); context.beginPath(); context.arc(x, y, radius, 0, Math.PI * 2, false); context.arc(x*2, y*2, radius, 0, Math.PI * 2, false); context.arc(x*3, y*3, radius, 0, Math.PI * 2, false); context.arc(x*4, y*4, radius, 0, Math.PI * 2, false); context.arc(x*5, y*5, radius, 0, Math.PI * 2, false); context.arc(x*6, y*6, radius, 0, Math.PI * 2, false); context.fill(); } }); [/cc]Follow the whole Interactive Physics Animations via Javascript & Canvas series.

Interactive Physics Animations Javascript Canvas 02

Adding more circles, each a multiple of the first circle’s coordinates. I like the effect of having them all move in unison. Ceck the source: interactive physics animations via javascript & canvas | 02

[cc lang=”javascript”]
$(function () {
var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

canvas = $(“#canvas”)[0];
context = canvas.getContext(“2d”);
width = canvas.width;
height = canvas.height;
x = width / 2;
y = height / 2;
draw();

$(“#canvas”).mousedown(function (event) {
var dx, dy, dist;
dx = event.pageX – this.offsetLeft – x;
dy = event.pageY – this.offsetTop – y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) { drag = true; clickX = dx; clickY = dy; } else { drag = false; } }); $("#canvas").mouseup(function (event) { drag = false; }); $("#canvas").mousemove(function (event) { if(drag) { x = event.pageX - this.offsetLeft - clickX; y = event.pageY - this.offsetTop - clickY; draw(); } }); function draw() { context.clearRect(0, 0, width, height); context.beginPath(); context.arc(x, y, radius, 0, Math.PI * 2, false); context.arc(x*2, y*2, radius, 0, Math.PI * 2, false); context.arc(x*3, y*3, radius, 0, Math.PI * 2, false); context.arc(x*4, y*4, radius, 0, Math.PI * 2, false); context.arc(x*5, y*5, radius, 0, Math.PI * 2, false); context.arc(x*6, y*6, radius, 0, Math.PI * 2, false); context.fill(); } }); [/cc]

Interactive Physics Animations Javascript Canvas 01

Adding a second circle, always at twice the x and y as the first. The first is still draggable. View the source: interactive physics animations via javascript & canvas | 01

[cc lang=”javascript”]
$(function () {
var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

canvas = $(“#canvas”)[0];
context = canvas.getContext(“2d”);
width = canvas.width;
height = canvas.height;
x = width / 2;
y = height / 2;
draw();

$(“#canvas”).mousedown(function (event) {
var dx, dy, dist;
dx = event.pageX – this.offsetLeft – x;
dy = event.pageY – this.offsetTop – y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) { drag = true; clickX = dx; clickY = dy; } else { drag = false; } }); $("#canvas").mouseup(function (event) { drag = false; }); $("#canvas").mousemove(function (event) { if(drag) { x = event.pageX - this.offsetLeft - clickX; y = event.pageY - this.offsetTop - clickY; draw(); } }); function draw() { context.clearRect(0, 0, width, height); context.beginPath(); context.arc(x, y, radius, 0, Math.PI * 2, false); context.arc(x*2, y*2, radius, 0, Math.PI * 2, false); context.fill(); } }); [/cc]

Interactive Javascript Canvas 00

I’ve played a lot with physics experiments in flash and moving more to javascript and canvas for simple things I wanted to test it out with some physics and animations. I’ve been curious to find out how the performance compares. Obviously this will depend on the browser, but the browsers that do support canvas should be able to handle some interactive physics animations.

I have this project I keep coming back to, it’s been in as2 and then in as3 and has have multiple faces. But the gist is there are a bunch of circles or balls and they float around in a specified area. There are physics “controls” exposed to the user and they can control the velocity of the balls, the gravity, air friction or drag, elasticity and they can even grab a ball and throw it across the stage (canvas). Here are a couple iterations of this: BFA Portfolio, Current Interactive POG Portfolio, Dribbble likes, Lastfm scrobbles.

I’m going to rebuild the basic functionality via javascript. I have had this on my list of things to explore for months now, in fact, ever since I saw Keith Peters go through his month long javascript exploration, he had a specific example that made me think I really needed to do it. I started and then life happened… But now I’m ready to start documenting my progress and trying to share what I’ve learned.

I’ll start with his initial example he titles JavaScript Day 27: Mouse Part II.
View my version here: interactive physics animations via javascript & canvas.

[cc lang=”javascript”]
$(function () {
var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

canvas = $(“#canvas”)[0];
context = canvas.getContext(“2d”);
width = canvas.width;
height = canvas.height;
x = width / 2;
y = height / 2;
draw();

$(“#canvas”).mousedown(function (event) {
var dx, dy, dist;
dx = event.pageX – this.offsetLeft – x;
dy = event.pageY – this.offsetTop – y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) { drag = true; clickX = dx; clickY = dy; } else { drag = false; } }); $("#canvas").mouseup(function (event) { drag = false; }); $("#canvas").mousemove(function (event) { if(drag) { x = event.pageX - this.offsetLeft - clickX; y = event.pageY - this.offsetTop - clickY; draw(); } }); function draw() { context.clearRect(0, 0, width, height); context.beginPath(); context.arc(x, y, radius, 0, Math.PI * 2, false); context.fill(); } }); [/cc]

Interactive Javascript Canvas Series

I’ve been playing with canvas and different javascript drawing libraries a lot lately in my projects at work. I’ve been antsy to play with the techniques I’ve learned and apply it to some more interactive experiments. Much like my last series on generative art in flash, but this will all be in javascript! In case you’re extra interested in this type of stuff, go check out Keith Peters’ month long exploration into javascript on his bit-101 site, he’s did some great stuff, and I learned a lot from that. I’m not going to sign up to post every day or anything, but I’ll keep it going for a while at least. So, stay tuned! And let me know if you’re really wanting to see this go into any specific directions.

Here goes nothin’

Hiatus Apologies

I’ve neglected this site lately, 6 months to be exact. Combine busy times, new jobs, summer trips skipping the country and websites are sometimes the first to be neglected.

oh canada

But, I’m planning on being back. I want to shift towards sharing more links and quick tips, partly because reading the internet had become more of a 140 characters ADHD process. I’ll be writing less tutorials in the sense that I’ve been writing, but I’m planning on having much more content, just less demanding on my time. I don’t have time to write a book and no one wants to read it anyways (myself included). We just want to see cool new things and tips and quick solutions to issues. So, I’m going to be sharing a lot more links pointing to cool things and tricks. I’ve shifted from flash animation it seems to more jQuery and CMS programming and less flash. But I don’t mind too much, although I still enjoy flash immensely, many of the same things we once had to rely on plugins to achieve, we can now do with javascript. It’s really the same end result just using different technologies. So expect some snippets and quick examples rather than complete walkthroughs. I’ll focus on all things interactive (as usual) but will include a broader range of things.

On another note, I’ve started a new job (again). I’m now at The Jones Group, downtown Atlanta. The advertising industry wasn’t for me, and I’m happy to be Interactive Director at the Jones Group working on making some really cool & interactive websites! You can bet, I’ll be sharing details of them as they launch (I’ve actually got a backlog waiting already).

circlecube Relaunch

Not just a redesign but a whole new site and location! After having built loads of sites for clients/friends I kept learning things I wanted to employ on my own site, but the cobblers kids are always barefoot right? I kept implementing new things and knew that they were making my clients lives easier and I wanted it easier as well.

circlecube logo
I’d already updated my logo a number of times since my last redesign and I wasn’t happy with how my collection of sites all looked different and required repetitive work to maintain. circlecube-sketch-3Well, I did some sketches and committed to working on it just a few minutes a day. I really work best as I visually think through a design so sketching is always the first step in my designs. After I nailed down the basic elements and concepts I needed in the site through sketches I installed a new wordpress site, the thematic framework and then got started on a child theme. I really surprised myself and in a mere couple weeks I had a short list of things to do before I could “flip the switch”. The hardest part by far was trying to do 301 redirects from all the old posts which lived on either my blog or portfolio sub-domains. But thanks to my friend we were able to iron that out and I learned more than I ever wanted to know about mod rewrites and such. I was able to combine my blog and portfolio and my home page all into one site. I always felt weird pushing friends/potential clients and everyone else to my blog or my landing page or portfolio… but now they can all simply go to the same place!

circlecube-sketch-1My goal was to enable all content to be updated in the back-end, I didn’t want any content in the theme. And I didn’t want to have to redo the css or layout to move something from the header to the footer or sidebar for example. I placed a lot of content in widgets and a few pages that were wholly widget areas. I also needed a portfolio section that displayed a little gallery of images and possibly flash content automatically. It needed to be easy if I were going to ever update the portfolio, so I used custom post types and custom fields to attach images and other data to each portfolio item. Then one of my favorite pages is the social page, it’s just a collection of my social feeds all displayed neatly in one place.

While I’d love to release the theme for everyone, I cheated and used quite a few plug-ins to accomplish my designs so the theme itself doesn’t include all the functionality and I’m pretty sure it’s bad for to require plug-ins and set up to get a theme functional, but if you’re interested, let me know.

As usually happens though, I learned some more tricks as I built this site. So I have a list of things I’m ready to write and share about on the blog: custom post types, custom taxonomies, thematic customizations, css tricks, fancybox, custom fields, jquery, widgets, htaccess, importing/exporting wordpress, new favorite plug-ins and more… So be excited!

My only regret so far is the lack of texture on the site so I may come back and apply slight noise to the site background to make it more tangible. But I also like the clean look. Well, to see snapshots of the site I added the circlecube redesign to the portfolio section of this site (cheesy to include my own site in my portfolio? yep, but I’m excited to use the feature and I always retrospectively wish I’d documented site updates).

Still, there may be a few things that don’t fully connect, so please, please let me know if you see anything broken or experience a broken link. But stay tuned for some posts since I’m not spending time building the site I’ll put a little time each day into putting content on the site again.

Javascript to show/hide elements update with jQuery

I never expected it, but one of the most popular (most commented) posts on this blog is a javascript post from about 3 years ago. I was showing how to hide and show elements on a web page with some simple javascript using getElementById and altering the display or visibility attributes of the element. It still works – although I hear every once in a while that certain browsers have issues with is sometimes, but the truth is I haven’t used this code almost since I wrote it. I have converted to jQuery! And it is much easier to code, easier to read and even nicer to browsers. So I’m writing this update post to proclaim the antiquity (3 years on the internet is a long time) of getElementById and the benefits of jQuery!

There isn’t much more to say about it really. I hope you’ve heard of jquery and if not, please go check it out it’s pretty easy to pick up! One thing I will mention is the potential bloat to having to load a javascript library. But most of my projects lately have included jQuery because I’ve been using it much more than just showing and hiding elements. But remember our friend cache? Remember that if you’re using jQuery on a whole site, the user only loads it once, and if you load it from the google hosted version of jQuery they likely will already have the script in their cache. The current version is hosted at http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js, so just link to that script on your page and you’re free to throw in any jquery onto your page.

Well, check out the code; I hope it’s pretty self explanatory and you can see it in action. I always have to see things work to understand them and learn from them.

Javascript

[cc lang=”javascript”]
$(document).ready(function() {

$(‘.hide_it’).click(function(){ $(‘.to_hide’).hide(); });

$(“.show_it”).click(function () { $(“.to_show”).show(“slow”); });

$(“#toggle_it”).click(function () { $(“.to_toggle”).toggle(); });

$(‘.fade_it’).click(function() { $(“.to_fade”).fadeTo(“slow”,0); });

$(‘.fade_out’).click(function() { $(“.to_fade_out”).fadeOut(); });

$(‘.reset_all’).click(function() {
$(‘.to_hide’).show();
$(“.to_show”).hide();
$(“.to_toggle”).show();
$(“.to_fade”).fadeTo(“slow”,100);
$(“.to_fade_out”).fadeIn();
});
});
[/cc]

show-hide-jquery-screenshot

HTML Code

see it in action on the demo page
[cc lang=”html”]

testing hide js div

hide it


Show me slowly.


testing the toggle functionality of jQuery


testing fade out. you’ll notice that this is set to display:none once the fade is complete.

fade out


testing fade to 0. this fades out just as fadeOut, but it does no make the display none, so the page layout isn’t modified, just the visibility of this element.

fade it


[/cc]

Notice that with jQuery we can use a class or an id as a selector. This is great because you can show a whole slew of elements that share the same class at once. Remember that you can only have one id on a page at once since it must be unique.

See the demo page for working examples.

And don’t forget to read up on the api for jQuery here jQuery hide, jQuery show, jQuery toggle, jQuery fadeOut, jQuery fadeIn, jQuery fadeTo.

Better jquery mega-menu tutorial

My earlier simple mega menu implementation post displayed some simple css and jquery to explode a standard navigation menu into a mega-menu… I’ve made it even better. My biggest issue with that implementation was that it did not keep the order like you’d expect. It read left to right in columns rather than down each column. In the example you can see the first column of three would read from the top: a, d, g, j… this could potentially be confusing. So I wanted to update it to keep the order better and just stack the columns of elements rather than the elements themselves.

I used some different jquery to execute this. First we walk through the menu elements and calculate which column they should be in. We basically map that element’s (li)index to the column it should be, some big math. Luckily I had some experience from actionscript in my arsenal doing just that, so porting the function to javascript I was ready to go. If your number X falls between A and B, and you would like to convert it to Y which falls between C and D follow this formula: Y = (X-A)/(B-A) * (D-C) + C. Plugging this function in and cancelling out the zeros and adding some rounding to get integers I got: Math.floor((liindex / $total * $cols)+1). Using this I added a class to each ‘li’ designating which column it should be in, and then used wrapAll to wrap them into column divs. Very simple and a much better implementation overall anyways. Better code, better user experience… what more can you ask… so here’s the example and jquery code. I’m thinking I should make this into a jquery plugin or something, any thoughts?

better-mega-menu-screenshot

See the mega menu in action

Javascript code

[cc lang=”javascript”]
jQuery(document).ready(function() {
//clean up the row of the mega menu. add css class to each element on bottom row.
//only if more than 7 elements. if more than 16, mm-3
jQuery(‘#nav li ul’).each(function(ulindex, ulele){
$total = jQuery(this).children(‘li’).size();
if ($total <= 7) { jQuery(this).addClass('mm-1'); } else { $cols = Math.floor(($total) / 8) + 1; $remainder = $total % $cols; $rows = Math.ceil($total / $cols); jQuery(this).addClass('mm-' + $cols + ' total-' + $total + ' rem-'+$remainder );jQuery(this).children().each(function(liindex, liele){ //alert("total: "+$total+", remainder: "+ $mod+", ulindex: "+ulindex+", liindex: "+liindex); //If your number X falls between A and B, and you would like to convert it to Y which falls between C and D follow this formula: Y = (X-A)/(B-A) * (D-C) + C. jQuery(this).addClass('col-' + Math.floor((liindex / $total * $cols)+1) ); if( (liindex+1) % $rows == 0) { jQuery(this).addClass('last'); } });for (var colcount = 1; colcount<= $cols; colcount++){ jQuery(this).children('.col-'+colcount).wrapAll('

‘);
}
}
});
});
[/cc]

css

[cc lang=”css”]
ul { list-style:none; }

/********** < Navigation */ .nav-container { float:left; background: #398301; margin: 10em 0; width: 960px; } #nav { border: 0px none; padding:3px 0 2px 44px; margin:0; font-size:13px; }/* All Levels */ #nav li { text-align:left; position:relative; } #nav li.over { z-index:999; } #nav li.parent {} #nav li a { display:block; text-decoration:none; } #nav li a:hover { text-decoration:none; } #nav li a span { display:block; white-space:nowrap; cursor:pointer; } #nav li ul a span { white-space:normal; }/* 1st Level */ #nav li { float:left; } #nav li a { float:left; padding:5px 10px; font-weight:normal; color: #fff; text-shadow: 1px 1px #1b3f00; } #nav li a:hover { color: #fff; text-shadow: 1px 1px 3px #ccc; } #nav li.over a, #nav li.active a { color:#fff; }/* 2nd Level */ #nav ul { position:absolute; width:15em; top:26px; left:-10000px; border:1px solid #1b3f00; border-width: 0 1px 2px 1px; background:#398301; padding: 6px 0 6px; } #nav ul div.col { float:left; width: 15em; } #nav ul li { float:left; padding: 0; width: 15em; } #nav ul li a { float:none; padding:6px 9px; font-weight:normal; color:#FFF !important; text-shadow: 1px 1px #1b3f00; border-bottom:1px solid #1b3f00; background:#398301; } #nav ul li a:hover { color:#fff !important; text-shadow: 1px 1px 3px #ccc; background: #2b6301; } #nav ul li.last > a { border-bottom:0; }
#nav ul li.last.parent > a { border-bottom:0; }

#nav ul li.over > a { font-weight:normal; color:#fff !important; background: #1b3f00; }
#nav ul.mm-1 { width: 15em; }
#nav ul.mm-2 { width: 30em; }
#nav ul.mm-3 { width: 45em; }
#nav ul.mm-4 { width: 60em; }
/* 3rd+ leven */
#nav ul ul { top:-6px; background: #1b3f00; }

/* Show Menu – uses built-in magento menu hovering */
#nav li.over > ul { left:0; }
#nav li.over > ul li.over > ul { left:14em; }
#nav li.over ul ul { left:-10000px; }

/* Show Menu – uses css only, not fully across all browsers but, for the purpose of the demo is fine by me */
#nav li:hover > ul { left:0; z-index: 100; }
#nav li:hover > ul li:hover > ul { left:14em; z-index: 200; }
#nav li:hover ul ul { left:-10000px; }
[/cc]

Download

Visit this demo page and view source or save as…

A simple mega menu implementation with CSS and jquery

I’ve been skinning quite a few ecommerce sites with the magento platform and wanted a simple way to explode the navigation menus. Some sites end up getting a long list of categories and sub-categories, so I wanted to do a mega-menu style navigation. One way to do it was to rewrite the html code for the navigation and pop each column into another nested unordered list. I’m not a fan of doing this because one – I didn’t want to manipulate the html. I like the simplicity of ul navigation with a clear flat list of li elements. Of course for nested sub-navigation any li can contain another ul. I wanted to just use some css and maybe javascript to visually accomplish the same thing. I also wanted it to be portable, so I could take it and use it on a wordpress install or even a plain html site. I went to my favorite: jquery. I knew there was a likely plugin out there already that would do something similar, but nothing after my initial search, but I realized that it was a simple procedure and mostly accomplished with some css.
mega menu screenshot
I’ll walk you through the process here and let you inspect the code yourself and see it in action on the demo page. Assign each ul to be a default width of 15em, then each li element we float:left and also give it a width of 15em. This way we can change the ul width to 30em and automatically I have 2 columns! Assigning the nested ul a specific width according to it’s class is done through css, mm-0 will be 15em and incrementally each next one will be 15em more. mm-1 is 30 and mm-2 is 45. Then we use jquery to determine the number of elements in the list and assign it a class accordingly. This involves some math and some preferences. Using the magic ui number 7, I determined that a menu with more than 7 elements should explode into multiple columns. So anything less than or equal to 7 I assign the class ‘mm-1’ which in the css sets the width to the standard 15em (ie 1 mega menu column). More than 7 should pop into columns no more than 8 tall. So dividing the total by 8 will give us the number of columns we want. We’ll add a class of mm-x, where x would be the number of columns. And the li elements will float to the left and fill in the space in columns.
One specific issue is the last element in the menu, sometimes we need to style that element differently. I’ll loop through each child of the nested ul element and if it is on the bottom row apply a class of ‘last’. But this was a little tricky in calculating which would be last because were never sure how many elements there will be or how many columns. I just used the remainder after dividing the total by the number of columns, then if the remainder could be used to know which elements are on the bottom row.

OK, now that that’s out of the way, let’s look at the code.

HTML

This I won’t show, you can inspect the source of the demo if you wish to see it, it a basic nested collection of unordered lists. It’s the standard that is created by magento, wordpress and most other CMS platforms.

CSS

[cc lang=”css”]
html, body { margin:0; padding:0; }
ul { list-style:none; }

/********** < Navigation */ .nav-container { float:left; background: #186C94; margin: 10em 0; width: 960px; } #nav { border: 0px none; padding:3px 0 2px 44px; margin:0; font-size:13px; }/* All Levels */ #nav li { text-align:left; position:relative; } #nav li.over { z-index:999; } #nav li.parent {} #nav li a { display:block; text-decoration:none; } #nav li a:hover { text-decoration:none; } #nav li a span { display:block; white-space:nowrap; cursor:pointer; } #nav li ul a span { white-space:normal; }/* 1st Level */ #nav li { float:left; } #nav li a { float:left; padding:5px 10px; font-weight:normal; color: #fff; text-shadow: 1px 1px #111; } #nav li a:hover { color: #fff; text-shadow: 1px 1px 3px #ccc; } #nav li.over a, #nav li.active a { color:#fff; }/* 2nd Level */ #nav ul { position:absolute; width:15em; top:26px; left:-10000px; border:1px solid #104A65; border-width: 0 1px 2px 1px; background:#186C94; padding: 6px 0 6px; } #nav ul div.col { float:left; width: 15em; } #nav ul li { float:left; padding: 0; width: 15em; } #nav ul li a { float:none; padding:6px 9px; font-weight:normal; color:#FFF !important; text-shadow: 1px 1px #111; border-bottom:1px solid #104A65; background:#186C94; } #nav ul li a:hover { color:#fff !important; text-shadow: 1px 1px 3px #ccc; background: #135575; } #nav ul li.last > a { border-bottom:0; }
#nav ul li.last.parent > a { border-bottom:0; }

#nav ul li.over > a { font-weight:normal; color:#fff !important; background: #104A65; }
#nav ul.mm-1 { width: 15em; }
#nav ul.mm-2 { width: 30em; }
#nav ul.mm-3 { width: 45em; }
#nav ul.mm-4 { width: 60em; }
/* 3rd+ leven */
#nav ul ul { top:-6px; background: #104A65; }

/* Show Menu – uses built-in magento menu hovering */
#nav li.over > ul { left:0; }
#nav li.over > ul li.over > ul { left:14em; }
#nav li.over ul ul { left:-10000px; }

/* Show Menu – uses css only, not fully across all browsers but, for the purpose of the demo is fine by me */
#nav li:hover > ul { left:0; z-index: 100; }
#nav li:hover > ul li:hover > ul { left:14em; z-index: 200; }
#nav li:hover ul ul { left:-10000px; }
[/cc]

Javascript

Don’t forget to include jQuery (I prefer using the google hosted version at http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js)
[cc lang=”javascript”]
jQuery(document).ready(function() {
//clean up the row of the mega menu. add css class to each element on bottom row.
//only if more than 7 elements. if more than 16, mm-3
jQuery(‘#nav li ul’).each(function(ulindex, ulele){
$total = jQuery(this).children(‘li’).size();
if ($total <= 7) { jQuery(this).addClass('mm-1'); } else { $cols = Math.floor(($total) / 8) + 1; $remainder = $total % $cols; jQuery(this).addClass('mm-' + $cols + ' total-' + $total + ' rem-'+$remainder );jQuery(this).children().each(function(liindex, liele){ //alert("total: "+$total+", remainder: "+ $mod+", ulindex: "+ulindex+", liindex: "+liindex); if( liindex + $remainder >= $total || $remainder == 0 && liindex + $cols >= $total ){
//alert(“total: “+$total+”, remainder: “+ $remainder+”, index: “+liindex);
jQuery(this).addClass(‘last’);
}
});
}
});

});
[/cc]

See the demo in action