Javascript

Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

Smashing-magazine-advertisement in Five Useful CSS/jQuery Coding Techniques For More Dynamic WebsitesSpacer in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites
 in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites  in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites  in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

Interactivity can transform a dull static website into a dynamic tool that not only delights users but conveys information more effectively. In this post, we’ll walk through five different coding techniques that can be easily implemented on any website to provide a richer user experience.

The techniques will allow you to better display difficult content, help users find information more effectively and provide meaningful UI cues without overwhelming the user.

  1. On-page text search
  2. Drag controls for oversized content
  3. Subtle hover effects
  4. Comment count bars
  5. Full-page slider

[Offtopic: by the way, did you know that there is a Smashing eBook Series? Book #2 is Successful Freelancing for Web Designers, 260 pages for just $9,90.]

1. On-Page Text Search

E-read-search-instant in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

Websites often have search boxes to allow users to find content from their archives. But what if you want to find content on the given page? Information Architects has had on-page text search that provides a great user experience. Let’s recreate this using jQuery.

Mark-Up and Interaction

First let’s build an input box for the search:

<input type="text" id="text-search" />

Next we’ll need jQuery to attach a listener to track changes to the input box:

$(function() {
    $('#text-search').bind('keyup change', function(ev) {
        // pull in the new value
        var searchTerm = $(this).val();
    )};
});

Here we bound our function to both the keyup and change events. This ensures that our operation fires regardless of whether the user types or pastes the text.

Now, let’s turn to Highlight, a useful and lightweight jQuery plug-in that handles text highlighting. After including the plug-in source, let’s add a highlight() call to our JavaScript:

$(function() {
    $('#text-search').bind('keyup change', function(ev) {
        // pull in the new value
        var searchTerm = $(this).val();

        // disable highlighting if empty
        if ( searchTerm ) {
            // highlight the new term
            $('body').highlight( searchTerm );
        }
    });
});

In addition to highlighting the given text, we’ve also added a check to make sure the search term isn’t empty (which causes an infinite loop).

This snippet highlights the search query throughout the page, but we can also limit the scope to a given id:

$('#myId').highlight( searchTerm );

Or we can search only within a certain element:

$('p').highlight( searchTerm );

This text highlighting by default is case insensitive. If you’d prefer case-sensitive highlighting, remove the .toUpperCase() on both lines 21 and 41 of the Highlight plug-in.

Styling the Highlighted Text

Now that the JavaScript is attached, we’ll need to style our highlighted items. The Highlight plug-in wraps the highlighted terms in <span class="highlight"></span>, which we can style with CSS.

First, let’s change the background color and then add rounded corners and a drop-shadow for all browsers except IE:

.highlight {
    background-color: #fff34d;
    -moz-border-radius: 5px; /* FF1+ */
    -webkit-border-radius: 5px; /* Saf3-4 */
    border-radius: 5px; /* Opera 10.5, IE 9, Saf5, Chrome */
    -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.7); /* FF3.5+ */
    -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.7); /* Saf3.0+, Chrome */
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.7); /* Opera 10.5+, IE 9.0 */
}

Although the highlighting is now visible, it still appears a bit tight around the text and could use some padding. But we’ll have to be careful not to adjust the layout of text. These spans are inline elements, and if we simply add padding, the text will shift around on the page. So, let’s include padding with a negative margin to compensate:

.highlight {
    padding:1px 4px;
    margin:0 -4px;
}

Finishing the Interaction

Last but not least, let’s make sure to remove the highlighted text whenever the user edits text in the input box:

$(function() {
    $('#text-search').bind('keyup change', function(ev) {
        // pull in the new value
        var searchTerm = $(this).val();

        // remove any old highlighted terms
        $('body').removeHighlight();

        // disable highlighting if empty
        if ( searchTerm ) {
            // highlight the new term
            $('body').highlight( searchTerm );
        }
    });
});

Here we added a call to remove any text highlighting, which is performed outside of the empty field check. This ensures that the highlight is also removed if the user clears the field.

Although removeHighlight() works well in most browsers, it will crash IE6. This is due to an IE6 bug with node.normalize().

We can get the Highlight plug-in working in IE6 by rewriting this function. Simply replace lines 45-53 of highlight.js with the following:

jQuery.fn.removeHighlight = function() {
 function newNormalize(node) {
    for (var i = 0, children = node.childNodes, nodeCount = children.length; i < nodeCount; i++) {
        var child = children[i];
        if (child.nodeType == 1) {
            newNormalize(child);
            continue;
        }
        if (child.nodeType != 3) { continue; }
        var next = child.nextSibling;
        if (next == null || next.nodeType != 3) { continue; }
        var combined_text = child.nodeValue + next.nodeValue;
        new_node = node.ownerDocument.createTextNode(combined_text);
        node.insertBefore(new_node, child);
        node.removeChild(child);
        node.removeChild(next);
        i--;
        nodeCount--;
    }
 }

 return this.find("span.highlight").each(function() {
    var thisParent = this.parentNode;
    thisParent.replaceChild(this.firstChild, this);
    newNormalize(thisParent);
 }).end();
};

This new function replaces the standard Javascript normalize() with a custom function that works in all browsers.

Download the complete example.

2. Drag Controls For Oversized Content

Moscow in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

When layout constraints bump up against the need for large images, finding a quality solution can be difficult. Mospromstroy uses a creative technique to handle this situation: a "drag and drop" control bar that allows users to pan through images.

We can accomplish something similar using jQuery UI's draggable behavior.

Mark-Up and CSS

First let's set up some mark-up for the content and controls:

<div id="full-sized-area">
    <div id="full-sized-content">
    Your content here
    </div>
</div>

<div id="drag-controls-area">
    <div id="drag-controls"></div>
</div>

Next, let's apply some basic CSS:

#full-sized-area {
    position: relative;
    overflow: hidden;
    width: 800px;
    height: 400px;
}

#full-sized-content {
    position: absolute;
    top: 0;
    left: 0;
}

#drag-controls-area {
    position: relative;
    width: 300px;
    height: 50px;
}

#drag-controls {
    position: absolute;
    top: 0;
    left: 0;
    height: 48px;
    border: 1px solid white;
}

Here we applied an absolute position to both the #full-sized-content and #drag-controls, and we also hid any overflow from the large image. Additionally, we applied some arbitrary dimensions to the content and drag controls wrappers; make sure to adjust these as needed.

Building Interactivity With jQuery

Now, let's use jQuery UI to build the interaction. Begin by including jQuery UI with the draggable module.

Before attaching the controls, let's resize the drag control box to the right dimensions:

$(function() {
    var $fullArea = $('#full-sized-area');
    var $fullContent = $('#full-sized-content', $fullArea);

    // find what portion of the content is displayed
    var contentRatio = $fullArea.width() / $fullContent.width();

    // scale the controls box
    var $controlsArea = $('#drag-controls-area');
    var $controls = $('#drag-controls', $controlsArea);

    $controls.css('width', $controlsArea.width() * contentRatio);
});

Here, we've determined what portion of the content is visible in the content area and then scaled the width of the control box accordingly.

Next, let's attach the draggable behavior:

$(function() {
    var $fullArea = $('#full-sized-area');
    var $fullContent = $('#full-sized-content', $fullArea);

    // find what portion of the content is displayed
    var contentRatio = $fullArea.width() / $fullContent.width();

    // scale the controls box
    var $controlsArea = $('#drag-controls-area');
    var $controls = $('#drag-controls', $controlsArea);

    $controls.css('width', $controlsArea.width() * contentRatio);

    // determine the scale difference between the controls and content
    var scaleRatio = $controlsArea.width() / $fullContent.width();

    // attach the draggable behavior
    $controls.draggable({
        axis : 'x', // confine dragging to the x-axis
        containment : 'parent',
        drag : function(ev, ui) {
            // move the full sized content
            $fullContent.css('left', -1 * ui.position.left / scaleRatio );
        }
    });
});

Here, we've attached a draggable event and set a couple options. First, we set axis to restrict dragging to the x-axis, and then we set containment to confine dragging to the parent element (i.e. the controls wrapper).

Finally, we set up a drag listener to move the full-sized content according to how far the user has dragged the control. For this, we negatively positioned the content to the left by the drag amount multiplied by the ratio of the controls to the content.

Custom Cursors

The draggable content is working, but we still have room for improvement.

First let's add some more styling to the control box to make it more interactive. jQuery UI's draggable attaches two class names that we can use for this: ui-draggable and ui-draggable-dragging.

#drag-controls.ui-draggable {
    cursor: -moz-grab !important;
    cursor: -webkit-grab !important;
    cursor: e-resize;
}

#drag-controls.ui-draggable-dragging {
    cursor: -moz-grabbing !important;
    cursor: -webkit-grabbing !important;
    border-color: yellow;
}

In addition to applying a new border color to the active controls, this snippet also attaches a number of cursor properties, which use proprietary UI cursors available in Firefox and Safari, with a back-up for IE.

Because of the implementation of the cursor property, we had to "bootstrap" this together using !important. This ensures that the proprietary cursors are used if available, while allowing the default cursor to overwrite them in IE. Unfortunately, Chrome does not currently support -webkit-grab, so we leave it out of this implementation. If you'd prefer to use the back-up e-resize cursor in both Chrome and Safari, just remove the -webkit-grab and -webkit-grabbing properties.

Parallax Effect

Let's make the sliding animation more three-dimensional by adding a two-layer parallax effect. To do so, we simply add a background to our full-sized content area and animate it at a slower rate.

Add the mark-up first:

<div id="full-sized-area">
    <div id="full-sized-background">
    Your background here
    </div>

    <div id="full-sized-content">
    Your content here
    </div>
</div>

<div id="drag-controls-area">
    <div id="drag-controls"></div>
</div>

And then some basic styling:

#full-sized-background {
    position: absolute;
    top: 0;
    left: 0;
}

Here, we use absolute positioning to lock the background in place. Note that we did not need to attach a z-index, because we placed the background element before the content area in the mark-up.

Finally, let's add the background animation to our drag event:

    $fullBackground = $('#full-sized-background');

    $controls.draggable({
        axis : 'x', // confine dragging to the x-axis
        containment : 'parent',
        drag : function(ev, ui) {
            // move the full sized content
            var newContentPosition = -1 * ui.position.left / scaleRatio;
            $fullContent.css('left', newContentPosition);

            // move the background
            $fullBackground.css('left', newContentPosition * .4);
        }
    });

Here, we simply used the new position that we calculated for the main content and applied 40% of that change to the background. Adjust this value to change the speed of the parallax.

Download the complete example.

3. Subtle Hover Effects

Veerle in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

Veerle's blog uses subtle transitions to create a natural feel for mouse interactions. These can be easily accomplished using CSS3's transition property (and a jQuery back-up for unsupported browsers).

First, let's attach some CSS with the class subtle to all elements:

.subtle {
    background-color: #78776C;
    color: #BBBBAD;
}

.subtle:hover, .subtle:focus {
    background-color: #F6F7ED;
    color: #51514A;
}

Here, we've styled these elements with a background and text color and included a hover state using the pseudo-class :hover. Additionally, we included the :focus pseudo-class for active input and text-area elements.

This CSS causes the style to change immediately on hover, but we can apply a smoother transition using CSS3:

.subtle {
    -webkit-transition: background-color 500ms ease-in; /* Saf3.2+, Chrome */
    -moz-transition: background-color 500ms ease-in; /* FF3.7+ */
    -o-transition: background-color 500ms ease-in; /* Opera 10.5+ */
    transition: background-color 500ms ease-in; /* futureproofing */
    background-color: #78776C;
    color: #BBBBAD;
}

.subtle:hover, .subtle:focus {
    background-color: #F6F7ED;
    color: #51514A;
}

Here, we've attached a CSS3 transition that works in all modern browsers except IE. The transition property consists of three different values. The first is the CSS property to animate, and the second is the duration of the animation—in our case, background-color and 500 milliseconds, respectively. The third value allows us to specify an easing function, such as ease-in or linear.

jQuery Back-Up

Our subtle transitions now work across a variety of browsers, but let's include support for all users by leveraging a jQuery back-up technique.

First we'll need to detect whether the user's browser supports transition:

// make sure to execute this on page load
$(function() {
    // determine if the browser supports transition
    var thisStyle = document.body.style,
    supportsTransition = thisStyle.WebkitTransition !== undefined ||
        thisStyle.MozTransition !== undefined ||
        thisStyle.OTransition !== undefined ||
        thisStyle.transition !== undefined;
});

Here, we check whether the body element can use any of the browser-specific transition properties that we defined above.

If the browser doesn't support transition, we can apply the animation using jQuery. However, jQuery's animate() function does not natively support color-based animations. To accommodate our background-color animation, we'll have to include a small chunk of jQuery UI: the effects core.

After including jQuery UI, we'll need to attach the animation to the hover and focus event listeners:

// make sure to execute this on page load
$(function() {
    // determine if the browser supports transition
    var thisStyle = document.body.style,
    supportsTransition = thisStyle.WebkitTransition !== undefined ||
        thisStyle.MozTransition !== undefined ||
        thisStyle.OTransition !== undefined ||
        thisStyle.transition !== undefined;

    // assign jQuery transition if the browser doesn't support
    if ( ! supportsTransition ) {
        var defaultCSS = {
            backgroundColor: '#78776C'
        },
        hoverCSS = {
            backgroundColor: '#F6F7ED'
        };

        // loop through each button
        $('.subtle').each(function() {
            var $subtle = $(this);

            // bind an event listener for mouseover and focus
            $subtle.bind('mouseenter focus', function() {
                $subtle.animate(hoverCSS, 500, 'swing' );
            });

            // bind the reverse for mouseout and blur
            $subtle.bind('mouseleave blur', function(ev) {
                if ( ev.type == 'mouseleave' && ev.target == document.activeElement ) return false;

                $subtle.animate(defaultCSS, 500, 'swing' );
            });
        });
    }
});

Here, we recreated the transition using jQuery's animate(). Notice how we used values that are to the CSS3 transition—500 specifies 500 milliseconds, and swing specifies an easing method that is close to ease-in.

While the mouse-over and focus event is fairly straightforward, notice the difference in the mouse-out and blur event. We added some code to end the function if the element is in focus. This retains the active state even if the user moves their mouse. jQuery's is() method does not support the :focus pseudo-class, so we have to rely on DOM's document.activeElement.

Download the complete example.

4. Comment Count Bars

Most-commented in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

IT Expert Voice uses a nice method for displaying the "Most commented" posts in its sidebar. Let's recreate this using WordPress and a bit of CSS and jQuery (non-WordPress users can skip the first section).

Pulling Posts With WordPress

Let's start by pulling in the top-five most-commented posts:

<?php $most_commented = new WP_Query('orderby=comment_count&posts_per_page=5'); ?>

Here, we used WP_Query and a custom variable name so as not to disrupt any other post loops on the page.

Next, let's loop through the posts we've selected, outputting each as a list item:

<ul id="most-commented">

<?php $most_commented = new WP_Query('orderby=comment_count&posts_per_page=5'); ?>
	<?php while ($most_commented->have_posts()) : $most_commented->the_post(); ?>	

	<li>
	<a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a>

	<span class="comment-bar"><span class="comment-count"><?php comments_number('0','1','%'); ?></span></span>
	</li>

<?php endwhile; ?>

</ul>

Here, we used a while() loop to run through each post. First, we output a link to the post using the_permalink() and the_title(), and then we output the comment count using comments_number() and some additional mark-up for styling.

Basic CSS Styling

Let's style the basic layout of the comments list using CSS:

#most-commented li {
    list-style: none;
}

#most-commented a {
    display: block;
}

We've removed any list styling and defined the links as a block element so that they stay separate from our comment bar visualizations.

Let's set up some base styles for the comment bar and comment count:

#most-commented .comment-bar {
    display: inline-block;
    position: relative;
    height: 30px;
    width: 0;
    margin: 5px 0;
    padding-left: 20px;
    background-color: #999;
}

#most-commented .comment-count {
    display: inline-block;
    position: absolute;
    right: -20px;
    top: -5px;
    width: 34px;
    height: 34px;
    border-width: 3px;
    border-style: solid;
    border-color: #FFF;
    -moz-border-radius: 20px;
    -webkit-border-radius: 20px;
    border-radius: 20px;
    text-align: center;
    line-height: 34px;
    background-color: #6CAC1F;
    font-size: 13px;
    font-weight: bold;
    color: #FFF;
}

Most of this styling is arbitrary, so feel free to attach a background image or otherwise tweak it to fit your theme. The main thing is to align the comment count to the right of the comment bar so that we can adjust the width of the bar at will.

Pay attention to the total width of the comment count, in our case 40px (34px wide plus 3px for the left and right borders). We're using half of that value to position the comment count: 20px of negative positioning so that the count hangs on the right, and 20px of left padding so that the comment bar reaches the center of the comment count.

Tying It All Together With jQuery

Finally, let's use jQuery to set the widths of the individual bars. We'll start by looping through the comments after the page loads:

$(function() {
    $('#most-commented li').each(function(i) {
        var $this = $(this);
        var thisCount = ~~$this.find('.comment-count').text();
    });
});

We loop through all of the <li> elements, pulling out the comment count from the mark-up. Notice that we've used the primitive data type ~~ to convert the text to an integer. This is significantly faster than alternatives such as parseInt().

Let's set up some key variables in the first iteration of our loop:

$(function() {
    // define global variables
    var maxWidth, maxCount;

    $('#most-commented li').each(function(i) {
        var $this = $(this);
        var thisCount = ~~$this.find('.comment-count').text();

        // set up some variables if the first iteration
        if ( i == 0 ) {
            maxWidth = $this.width() - 40;
            maxCount = thisCount;
        }
    });
});

Here, we started by defining variables outside of the each() loop. This allows us to use these values in every iteration.

Next, we subtracted 40 pixels from the width of the list item to define a maximum width for the comment bar. The 40 pixels compensate for the left-padding and negative position that we applied above.

We also set maxCount to the first value. Because we initially pulled the posts according to their number of comments, we can be sure that the first item will have the highest count.

Finally, let's calculate the width of each bar and animate the transition:

$(function() {
    // define global variables
    var maxWidth, maxCount;

    $('#most-commented li').each(function(i) {
        var $this = $(this);
        var thisCount = ~~$this.find('.comment-count').text();

        // set up some variables if the first iteration
        if ( i == 0 ) {
            maxWidth = $this.width() - 40;
            maxCount = thisCount;
        }

        // calculate the width based on the count ratio
        var thisWidth = (thisCount / maxCount) * maxWidth;

        // apply the width to the bar
        $this.find('.comment-bar').animate({
            width : thisWidth
        }, 200, 'swing');
    });
});

If you'd rather style the elements without any animation, simply replace the animate() with a static css().

Download the complete example.

5. Full-Page Slider

Wine-jax in Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

Sliding animation is an interactive way to show related content. But JAX Vineyards takes the standard sliding gallery to the next level by animating across the entire page. Let's create a similar effect using jQuery.

Mark-Up and CSS

Start by adding the mark-up:

<div id="full-slider-wrapper">
    <div id="full-slider">

        <div class="slide-panel active">
        Panel 1 content here
        </div>

        <div class="slide-panel">
        Panel 2 content here
        </div>

        <div class="slide-panel">
        Panel 3 content here
        </div>
    </div>
</div>

We set up the basic mark-up and wrappers that we need for the animation. Make sure that the full-slider-wrapper is not contained in any element that is narrower than the browser window—we'll need the full width of the browser to pull off the effect.

Now, let's add some basic CSS to handle overflow and to position the panels:

html {
    min-width: 800px;
}

#full-slider-wrapper {
    overflow: hidden;
}

#full-slider {
    position: relative;
    width: 800px;
    height: 600px;
    margin: 0 auto;
}

#full-slider .slide-panel {
    position: absolute;
    top: 0;
    left: 0;
    width: 800px;
    height: 600px;
    visibility: hidden;
}

#full-slider .slide-panel.active {
    visibility: visible;
}

We defined absolute positioning and set up some arbitrary dimensions for the panels and wrapper. Feel free to tweak these dimensions to your content.

We also attached overflow: hidden to our wrapper element, which will prevent scroll bars from appearing when we animate the panels. Because we hid the overflow, we also had to assign a min-width to the html document. This ensures that the content will get scroll bars if the browser window is too small.

Finally, we used the active class that we established in the mark-up to show the first panel.

jQuery Animation

Let's build the interaction using jQuery. We'll start by defining some variables and then create a function to handle the sliding animation in both directions:

$(function() {
    var $slider = $('#full-slider');
    var $sliderPanels = $slider.children('.slide-panel');

    function slidePanel( newPanel, direction ) {
        // define the offset of the slider obj, vis a vis the document
        var offsetLeft = $slider.offset().left;

        // offset required to hide the content off to the left / right
        var hideLeft = -1 * ( offsetLeft + $slider.width() );
        var hideRight = $(window).width() - offsetLeft;

        // change the current / next positions based on the direction of the animation
        if ( direction == 'left' ) {
            currPos = hideLeft;
            nextPos = hideRight;
        }
        else {
            currPos = hideRight;
            nextPos = hideLeft;
        }

        // slide out the current panel, then remove the active class
        $slider.children('.slide-panel.active').animate({
            left: currPos
        }, 500, function() {
            $(this).removeClass('active');
        });

        // slide in the next panel after adding the active class
        $( $sliderPanels[newPanel] ).css('left', nextPos).addClass('active').animate({
            left: 0
        }, 500 );
    }
});

Here our slidePanel() function accepts two arguments: the index of the panel that we want to slide into view, and the direction of the slide (i.e. left or right).

Although this function looks complicated, the concepts are fairly simple. We determined the amount of offset necessary to hide the panels on the left and right sides. To calculate these values, we used jQuery's offset() and the slider and window widths. These offsets represent the left position values needed to hide the content on either side.

Next, we have a switch based on the direction of the animation, which uses the two values we defined previously.

Finally, we trigger the animation using jQuery's animate(). We slide the active panel out of view and then remove the active class once the animation completes. Then we set the new panel's left position off the screen, attach the active class to make it visible and slide it into place.

Building the Controls

Our function now handles the animation, but we still have to build controls to leverage it.

Append navigation elements to the slider object that we defined previously:

    var $navWrap = $('<div id="full-slider-nav"></div>').appendTo( $slider );
    var $navLeft = $('<div id="full-slider-nav-left"></div>').appendTo( $navWrap );
    var $navRight = $('<div id="full-slider-nav-right"></div>').appendTo( $navWrap );

We could have included this navigation in the initial mark-up, but we're appending it with JavaScript for two reasons: it ensures that the navigation won't appear until the JavaScript is loaded, and it keeps the navigation from being displayed on the off chance that JavaScript isn't enabled.

Let's style the navigation:

#full-slider-nav {
    position: absolute;
    top: 0;
    right: 0;
}

#full-slider-nav-left, #full-slider-nav-right {
    display: inline-block;
    height: 0;
    width: 0;
    margin-left: 15px;
    border: 20px solid transparent;
    cursor: pointer;
}

#full-slider-nav-left {
    border-right-color: #BBB;
}

#full-slider-nav-left:hover {
    border-right-color: #999;
}

#full-slider-nav-right {
    border-left-color: #BBB;
}

#full-slider-nav-right:hover {
    border-left-color: #999;
}

Here we absolute position the navigation to the top right. We also use a CSS triangle trick to quickly style the controls.

Let's attach our new slider navigation to the slidePanel() function that we defined previously:

    var $navWrap = $('<div id="full-slider-nav"></div>').appendTo( $slider );
    var $navLeft = $('<div id="full-slider-nav-left"></div>').appendTo( $navWrap );
    var $navRight = $('<div id="full-slider-nav-right"></div>').appendTo( $navWrap );

    var currPanel = 0;

    $navLeft.click(function() {
        currPanel--;

        // check if the new panel value is too small
        if ( currPanel < 0 ) currPanel = $sliderPanels.length - 1;

        slidePanel(currPanel, 'right');
    });

    $navRight.click(function() {
        currPanel++;

        // check if the new panel value is too big
        if ( currPanel >= $sliderPanels.length ) currPanel = 0;

        slidePanel(currPanel, 'left');
    });

This snippet assigns click events to the left and right navigation. In each, we change the value of currPanel according to the direction. If this new value falls outside of the available panels, we loop to the other end of our set. Finally, we trigger the slidePanel() function with the new panel and appropriate direction.

In our example, we built controls only for left and right navigation, but you could easily tweak this to have buttons for each panel. Simply pass the correct panel index to slidePanel.

Let's bring all the jQuery code together:

$(function() {
    function slidePanel( newPanel, direction ) {
        // define the offset of the slider obj, vis a vis the document
        var offsetLeft = $slider.offset().left;

        // offset required to hide the content off to the left / right
        var hideLeft = -1 * ( offsetLeft + $slider.width() );
        var hideRight = $(window).width() - offsetLeft;

        // change the current / next positions based on the direction of the animation
        if ( direction == 'left' ) {
            currPos = hideLeft;
            nextPos = hideRight;
        }
        else {
            currPos = hideRight;
            nextPos = hideLeft;
        }

        // slide out the current panel, then remove the active class
        $slider.children('.slide-panel.active').animate({
            left: currPos
        }, 500, function() {
            $(this).removeClass('active');
        });

        // slide in the next panel after adding the active class
        $( $sliderPanels[newPanel] ).css('left', nextPos).addClass('active').animate({
            left: 0
        }, 500 );
    }

    var $slider = $('#full-slider');
    var $sliderPanels = $slider.children('.slide-panel');

    var $navWrap = $('<div id="full-slider-nav"></div>').appendTo( $slider );
    var $navLeft = $('<div id="full-slider-nav-left"></div>').appendTo( $navWrap );
    var $navRight = $('<div id="full-slider-nav-right"></div>').appendTo( $navWrap );

    var currPanel = 0;

    $navLeft.click(function() {
        currPanel--;

        // check if the new panel value is too small
        if ( currPanel < 0 ) currPanel = $sliderPanels.length - 1;

        slidePanel(currPanel, 'right');
    });

    $navRight.click(function() {
        currPanel++;

        // check if the new panel value is too big
        if ( currPanel >= $sliderPanels.length ) currPanel = 0;

        slidePanel(currPanel, 'left');
    });
});

Download the complete example.

Final Thoughts

In this post we walked through a variety of methods for adding dynamic functionality to your websites. These techniques can be easily adapted to work with almost any site. The majority of these techniques rely on jQuery to provide interaction, but there are plenty of other approaches, both with and without jQuery. Please post any alternate solutions in the comments below, or fork the example files on github.

Furthermore, these five methods represent only a small portion of interactive techniques. Please post any links to other dynamic techniques and functionality in the comments below.

Related Posts

You may be interested in the following related posts:

(al)


© Jon Raasch for Smashing Magazine, 2010. | Permalink | Post a comment | Add to del.icio.us | Digg this | Stumble on StumbleUpon! | Tweet it! | Submit to Reddit | Forum Smashing Magazine
Post tags: ,


Snoopy: View-source on iPhone/iPad

Snoopy: View-source on iPhone/iPad:

Handy little JavaScript bookmarklet for viewing source on the go. (via)


Minimise file size with the YUI Compressor TextMate Bundle

It’s quite obvious that the smaller the files that make up your website are, the less time your visitors will wait for them to download. One way of reducing file sizes is minimising JavaScript and CSS files by removing comments and whitespace, among other things.

To do that, you can either let the server do it for you or minimise the files yourself before uploading them to the server. Letting the server do it automatically is probably the most convenient way since you don't have to remember to do it. But it isn't practical or possible for everyone to use something like minify, so sometimes you'll need to do it manually.

That may sound like more trouble than it's worth. Luckily for us TextMate users there's a handy YUI Compressor TextMate bundle that makes it almost as transparent as the server-side solution.

Read full post

Posted in , , .



jQuery Plugin Checklist: Should You Use That jQuery Plug-In?

Smashing-magazine-advertisement in jQuery Plugin Checklist: Should You Use That jQuery Plug-In?Spacer in jQuery Plugin Checklist: Should You Use That jQuery Plug-In?
 in jQuery Plugin Checklist: Should You Use That jQuery Plug-In?  in jQuery Plugin Checklist: Should You Use That jQuery Plug-In?  in jQuery Plugin Checklist: Should You Use That jQuery Plug-In?

jQuery plug-ins provide an excellent way to save time and streamline development, allowing programmers to avoid having to build every component from scratch. But plug-ins are also a wild card that introduce an element of uncertainty into any code base. A good plug-in saves countless development hours; a bad plug-in leads to bug fixes that take longer than actually building the component from scratch.

Fortunately, one usually has a number of different plug-ins to choose from. But even if you have only one, figure out whether it’s worth using at all. The last thing you want to do is introduce bad code into your code base.

[Offtopic: by the way, did you know that we are publishing a Smashing eBook Series? The brand new eBook #3 is Mastering Photoshop For Web Design, written by our Photoshop-expert Thomas Giannattasio.]

Do You Need A Plug-In At All?

The first step is to figure out whether you even need a plug-in. If you don’t, you’ll save yourself both file size and time.

1. Would Writing It Yourself Be Better?

If the functionality is simple enough, you could consider writing it yourself. jQuery plug-ins often come bundled with a wide variety of features, which might be overkill for your situation. In these cases, writing any simple functionality by hand often makes more sense. Of course, the benefits have to be weighed against the amount of work involved.

For example, jQuery UI’s accordion is great if you need advanced functionality, but it might be overkill if you just need panels that open and close. If you don’t already use jQuery UI elsewhere on your website, consider instead the native jQuery slideToggle() or animate().

2. Is It Similar to a Plug-In You’re Already Using?

After discovering that a particular plug-in doesn’t handle everything you need, finding another plug-in to cover loose ends might be tempting. But including two similar plug-ins in the same app is a sure path to bloated JavaScript.

Can you find a single plug-in that covers everything you need? If not, can you extend one of the plug-ins you have to cover everything you need? Again, in deciding whether to extend a plug-in, weigh the benefits against the development time involved.

For example, jQuery lightbox is a nice way to enable pop-up photos in a gallery, and simpleModal is a great way to display modal messages to users. But why would you use both on the same website? You could easily extend one to cover both uses. Better yet, find one plug-in that covers everything, such as Colorbox.

3. Do You Even Need JavaScript?

In some situations, JavaScript isn’t needed at all. CSS pseudo-selectors such as :hover and CSS3 transitions can cover a variety of dynamic functionality much faster than a comparable JavaScript solution. Also, many plug-ins apply only styling; doing this with mark-up and CSS might make more sense.

For example, plug-ins such as jQuery Tooltip are indispensable if you have dynamic content that requires well-placed tooltips. But if you use tooltips in only a few select locations, using pure CSS is better (see this example). You can take static tooltips a step further by animating the effect using a CSS3 transition, but bear in mind that the animation will work only in certain browsers.

Avoid Red Flags

When reviewing any plug-in, a number of warning signs will indicate poor quality. Here, we’ll look at all aspects of plug-ins, from the JavaScript to the CSS to the mark-up. We’ll even consider how plug-ins are released. None of these red flags alone should eliminate any plug-in from consideration. You get what you pay for, and because you’re probably paying nothing, you should be willing to cut any one a bit of slack.

If you’re fortunate enough to have more than one option, these warning signs could help you narrow down your choice. But even if you have only one option, be prepared to forgo it if you see too many red flags. Save yourself the headache ahead of time.

4. Weird Option or Argument Syntax

After using jQuery for a while, developers get a sense of how most functions accept arguments. If a plug-in developer uses unusual syntax, it stands to reason that they don’t have much jQuery or JavaScript experience.

Some plug-ins accept a jQuery object as an argument but don’t allow chaining from that object; for example, $.myPlugin( $('a') ); but not $('a').myPlugin(); This is a big red flag.

A green flag would be a plug-in in this format…

$('.my-selector').myPlugin({
 opt1 : 75,
 opt2 : 'asdf'
});

… that also accepts…

$.myPlugin({
 opt1 : 75,
 opt2 : 'asdf'
}, $('.my-selector'));

5. Little to No Documentation

Without documentation, a plug-in can be very difficult to use, because that is the first place you look for answers to your questions. Documentation comes in a variety of formats; proper documentation is best, but well-commented code can work just as well. If documentation doesn’t exist or is just a blog post with a quick example, then you might want to consider other options.

Good documentation shows that the plug-in creator cares about users like you. It also shows that they have dug into other plug-ins enough to know the value of good documentation.

6. Poor History of Support

Lack of support indicates that finding help will be difficult when issues arise. More tellingly, it indicates that the plug-in has not been updated in a while. One advantage of open-source software is all of the eye-balls that are debugging and improving it. If the author never speaks to these people, the plug-in won’t grow.

When was the last time the plug-in you’re considering was updated? When was the last time a support request was answered? While not all plug-ins need as robust a support system as the jQuery plug-ins website, be wary of plug-ins that have never been modified.

A documented history of support, in which the author has responded to both bug and enhancement requests, is a green flag. A support forum further indicates that the plug-in is well supported, if not by the author then at least by the community.

7. No Minified Version

Though a fairly minor red flag, if the plug-in’s creator doesn’t provide a minified version along with the source code, then they may not be overly concerned with performance. Sure, you could minify it yourself, but this red flag isn’t about wasted time: it’s about the possibility that the plug-in contains far worse performance issues.

On the other hand, providing a minified, packed and gzipped version in the download package is an indication that the author cares about JavaScript performance.

8. Strange Mark-Up Requirements

If a plug-in requires mark-up, then the mark-up should be of high quality. It should make semantic sense and be flexible enough for your purposes. Besides indicating poor front-end skills, strange mark-up makes integration more difficult. A good plug-in plugs into just about any mark-up you use; a bad plug-in makes you jump through hoops.

In certain situations, more rigid mark-up is needed, so be prepared to judge this on a sliding scale. Basically, the more specific the functionality, the more specific the mark-up needed. Completely flexible mark-up that descends naturally from any jQuery selector is the easiest to integrate.

9. Excessive CSS

Many jQuery plug-ins come packaged with CSS, and the quality of the style sheets is just as important as the JavaScript. An excessive number of styles is a sure sign of bad CSS. But what constitutes “excessive” depends on the purpose of the plug-in. Something very display-heavy, such as a lightbox or UI plug-in, will need more CSS than something that drives a simple animation.

Good CSS styles a plug-in’s content effectively while allowing you to easily modify the styles to fit your theme.

10. No One Else Uses It

With the sheer volume of jQuery users, most decent plug-ins will probably have something written about them, even if it’s a “50 jQuery [fill in the blank]” post. Do a simple Google search for the plug-in. If you get very few results, you might want to consider another option, unless the plug-in is brand new or you can verifiy that it is written by a professional.

Posts on prominent blogs are great, and posts by prominent jQuery programmers are even better.

Final Assessment

After you’ve given the plug-in the third degree, the only thing left to do is plug it in and test how well it performs.

11. Plug It In and See

Probably the best way to test a plug-in is to simply plug it on the development server and see the results. First, does it break anything? Make sure to look at JavaScript in the surrounding areas. If the plug-in includes a style sheet, look for layout and styling errors on any page that applies the style sheet.

Additionally, how does the plug-in perform? If it runs slowly or the page lags considerably when loading, it might be important to consider other options.

12. Benchmarking With JSPerf

To take your performance review to the next level, run a benchmark test using JSPerf. Benchmarking basically runs a set of operations a number of times, and then returns an average of how long it took to execute. JSPerf provides an easy way to test how quickly a plug-in runs. This can be a great way to pick a winner between two seemingly identical plug-ins.

Jsperf in jQuery Plugin Checklist: Should You Use That jQuery Plug-In?
An example of a performance test run in jsPerf.

13. Cross-Browser Testing

If a plug-in comes with a lot of CSS, make sure to test the styling in all of the browsers that you want to support. Bear in mind that CSS can be drawn from external style sheets or from within the JavaScript itself.

Even if the plug-in doesn’t have any styling, check for JavaScript errors across browsers anyway (at least in the earliest version of IE that you support). jQuery’s core handles most cross-browser issues, but plug-ins invariably use some amount of pure JavaScript, which tends to break in older browsers.

14. Unit Testing

Finally, you may want to consider taking cross-browser testing even further with unit tests. Unit testing provides a simple way to test individual components of a plug-in in any browser or platform you want to support. If the plug-in’s author has included unit tests in their release, you can bet that all components of the plug-in will work across browsers and platforms.

Unfortunately, very few plug-ins include unit test data, but that doesn’t mean you can’t perform your own test using the QUnit plug-in.

With minimal set-up, you can test whether the plug-in methods return the desired results. If any test fails, don’t waste your time with the plug-in. In most cases, performing your own unit tests is overkill, but QUnit helps you determine the quality of a plug-in when it really counts. For more information on how to use QUnit, see this tutorial

Qunit-example in jQuery Plugin Checklist: Should You Use That jQuery Plug-In?
An example of a unit test run in QUnit.

Conclusion

When assessing the quality of a jQuery plug-in, look at all levels of the code. Is the JavaScript optimized and error-free? Is the CSS tuned and effective? Does the mark-up make semantic sense and have the flexibility you need? These questions all lead to the most important question: will this plug-in be easy to use?

jQuery core has been optimized and bug-checked not only by the core team but by the entire jQuery community. While holding jQuery plug-ins to the same standard would be unfair, they should stand up to at least some of that same scrutiny.

Related Posts

You may be interested in the following related posts:

(al)


© Jon Raasch for Smashing Magazine, 2010. | Permalink | Post a comment | Add to del.icio.us | Digg this | Stumble on StumbleUpon! | Tweet it! | Submit to Reddit | Forum Smashing Magazine
Post tags: , ,


Three Kick-Ass Web Developer Tutorials

Sometimes to get your development juices flowing you just need a meaty project or an in-depth tutorial that you can sink your teeth into and lose yourself for a few hours in coding bliss. And that’s what we have for you today, three tutorials that will satisfy your code craving! They are not only roll-up-your-sleeves and put-on-a-pot-of-coffee good but they will also introduce you to some of the latest CSS3, HTML5 and jQuery techniques.

A jQuery, CSS3 & HTML5 Hover-Based Interface

A jQuery, CSS3 & HTML5 Hover-Based Interface

In this awesome tutorial you will learn how to create a useful hover-based user interface using jQuery, CSS3, HTML5 and @font-face. The project you’ll be creating could easily be used for a portfolio or business site and the concepts you’ll learn could certainly be used to expand the idea further.
A jQuery, CSS3 & HTML5 Hover-Based Interface

Dynamic FAQ Section w/ jQuery, YQL & Google Docs

Dynamic FAQ Section w/ jQuery, YQL & Google Docs

In this tutorial, you will build a dynamic FAQ section. The script, with the help of jQuery & YQL, will pull the contents of a shared spreadsheet in your Google Docs account, and use the data to populate the FAQ section with questions and answers.
Dynamic FAQ Section w/ jQuery, YQL & Google Docs

How to easily create charts using jQuery and HTML5

How to easily create charts using jQuery and HTML5

For years, Flash was the only solution to display a dynamic chart on a website. But thanks to modern techniques, the dying Flash isn't needed anymore. In this tutorial,you'll be shown how easy it is to transform a basic HTML table into a profesionnal looking chart using visualize.js, a very useful jQuery plugin.
How to easily create charts using jQuery and HTML5

By Paul Andrew (Speckyboyand speckyboy@twitter).


  •   
  • Copyright © 1996-2010 BlogmyQuery - BMQ. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress