Tumblelog by Soup.io
Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

May 28 2013

16:46

A look at the custom tech behind the FT’s HTML5 mobile app

At Smashing Magazine, FT Labs front-end developer Wilson Page details some of the back-end tech behind the Financial Times’ shift from native apps to HTML5 on mobile platforms.

Among the highlights: using flexbox to fill defined vertical space, a JavaScript library called FTEllipsis to manage text flowing in a confined area, icon fonts for retina-ready images, and more natural-feeling scrolling. Much of the new code is open-sourced on the FT Labs GitHub.

We didn’t just want to build a product that fulfilled its current requirements; we wanted to build a foundation that we could innovate on in the future. This meant building with a maintenance-first mentality, writing clean, well-commented code and, at the same time, ensuring that our code could accommodate the demands of an ever-changing feature set.

April 02 2013

22:07

Using ECMAScript 5 Objects and Properties

ECMAScript 5's object and properties help you make your JavaScript stronger and safer.

September 05 2012

15:39

Miranda Mulligan: Want to produce hirable grads, journalism schools? Teach them to code

Editor’s Note: It’s the start of the school year, which means students are returning to journalism programs around the country. As the media industry continues to evolve, how well is new talent being trained, and how well are schools preparing them for the real world?

We asked an array of people — hiring editors, recent graduates, professors, technologists, deans — to evaluate the job j-schools are doing and to offer ideas for how they might improve. Over the coming days, we’ll be sharing their thoughts with you. Here’s Miranda Mulligan — new executive director of the Knight News Innovation Lab at Northwestern, formerly digital design director for The Boston Globe — arguing that journalists need to learn how to code if they want to become better (and employable) storytellers.

Learning how to make software for storytelling and how to realize news presentations into code are currently the hottest, most pressing skillsets journalists can study. There has never before been more urgency for our industry to understand enough code to have meaningful conversations with technologists.

And yet if you attend any event with a collection of jouro-nerd types, inevitably the same question will come up. Someone will ask — philosophically, of course — “How can we tell better stories on the web?” and proceed to bemoan the tedium of reading a daily newspaper and a newspaper website, likening it to Groundhog Day, the same stories presented the same way, day after day. Sooner or later others add their frustrations that “we” — in 2012 — are still writing for the front page instead of the homepage.

It is our job as educators to remove fear of learning, a fear notoriously prevalent in journalists.

We’ve all had this discussion a thousand times. But now, it’s not just the visual journalists complaining about the stagnation of online storytelling and presentation.

For me, there’s only one response to this: Journalists should learn more about code. Understanding our medium makes us better storytellers. For an industry that prides itself on being smart, tolerating ignorance of the Internet is just stupid.

The time is now for our future journalists to learn about code. We need to innovate our curricula, really looking at what we are teaching our students. Learning, or mastering, specific software is not properly preparing our future journalists for successful, life-long careers. No one can learn digital storytelling in a semester. Mastering Dreamweaver and Flash isn’t very future-friendly, and having a single mid-level “Online Journalism” course offered as an elective does more harm than good. We should be teaching code in all of our journalism courses — each semester, each year, until graduation.

The list of jobs for designers and journalists who can write code is growing — seemingly exponentially. So, let’s all grab our copies of The Art of War and attack this problem from every angle: We need to teach our students to be more technologically literate. We need to teach them how to learn and how to fail. That, my friends, is making the Internet.

I am not arguing that every single writer/editor/publisher who learns some programming should end up becoming a software engineer or a refined web designer. The end goal here is not programming fluency. However, there’s a lot of value in understanding how browsers read and render our stories. Reporting and writing a story, writing some code (HTML, CSS, Javascript), and programming complex applications and services are all collections of skills. A fundamental knowledge of code allows for:

  • More significant conversations about digital presentation, ultimately leading to better, more meaningful, online storytelling. Understanding your medium makes you better at your craft.
  • Deeper thought and understanding of data. Learning more about what goes into writing and programming software teaches you to think in terms of abstractions, functions, parameters, components, frameworks, object classes, templates, and more.

Journalism needs hirable graduates that can create sophisticated visual presentations and can realize them in code. But many students are intimidated, not excited, by the tools now fundamental to visual storytelling. In fact, the prevailing sentiment throughout journalism and communications specialties is that “we” are still intimidated. Maybe this attitude is trickling down to the universities — or maybe up from them. But “we” have all got to get over our fear of the Internet.

Last September, I participated in a half-day student seminar at the Society of News Design’s annual workshop in St. Louis. To be brazen and speak for my panel-mates, we were all shocked by how apprehensive the students were toward HTML, CSS, and Javascript. In fact, after three hours of nudging them to make the time to learn some code, a female student boldly asserted that she really didn’t care about digital design and wanted advice for students hoping to break into print design.

It’s our job as educators to remove fear of learning, a fear notoriously prevalent in journalists. HTML is not magic. Writing code is not wizardry; it’s just hard work. Learning to program will not save journalism and probably won’t change the way we write our stories. It is, however, a heck of a lot more fun being a journalist on the web once “how computers read and understand our content” is understood.

Learning to program not only provides a practical skill — it also teaches problem solving. Students are learning more precise and nuanced thought processes, and the depth of their understanding of information and data will only grow. Also, for visual journalists, teaching code is teaching information design. Both news designers and web designers are burdened with the same responsibilities: organizing and rationally arranging content, illustrating ideas to deepen the understanding of a story, and working within the constraints of the medium.

I believe the most important thing an instructor can ever do is inspire students to be open-minded about their skills. No one knows what the storytelling landscape will look like in two years, let alone a decade from now. As educators, we can make becoming a digital journalist feel accessible and attainable. Graduates should leave armed with a skillset that includes the ability to learn quickly and adapt, to be open to new ideas and solutions, and to take initiative like the self-starters they were born to become. They will never get bored, and they will always be employable.

Our journalism pedagogy should inspire future digital journalists to be Internauts, to continually grow, constantly teaching themselves the newest storytelling tools and techniques, instilling processes for life-long learning.

Image by Steve Rhode used under a Creative Commons license.

August 22 2012

20:39

HTML5, Apps and JavaScript Video

Watch video from the August 2012 TimesOpen event on HTML5, Apps and JavaScript.

August 17 2012

01:07

HTML5, Apps and JavaScript Wrap-Up

The first TimesOpen event of 2012 was a big success and a lot of fun.

August 02 2012

21:47

Announcing TimesOpen 2012

It's that time of the year again! We've just released our schedule for TimesOpen 2012. As always, we'll have four events leading up to an all-day hack day in December.

April 20 2012

06:26

Programming and journalism students: A conversation

I think it’s pretty cool to use Storify to sort out the threads of a bunch of simultaneous conversations on Twitter:

[View the story "Programming and journalism students: A conversation" on Storify]

Please join in — on Twitter, on Facebook, or here.

06:26

Programming and journalism students: A conversation

I think it’s pretty cool to use Storify to sort out the threads of a bunch of simultaneous conversations on Twitter:

[View the story "Programming and journalism students: A conversation" on Storify]

Please join in — on Twitter, on Facebook, or here.

January 17 2012

10:31
10:17

HOWTO: Native iPhone/iPad apps in JavaScript

"Create native-looking iPhone/iPad applications from HTML, CSS and JavaScript."

January 11 2011

21:46

October 31 2010

15:43

What are the Javascript libraries you depend on for programming?

I'm getting back into "real programming(tm)" with Javascript, after years of reaching for it only when I needed to manipulate a web page in the browser. As I dive back in, I'm stumbling on some great libraries, like Underscore.js (developed by the folks at DocumentCloud), persistence.js, and require.js, which make aspects of writing large programs in Javascript easier or faster.

So, I'm wondering what other libraries are out there that I should look at? What are the libraries that you rely on every day when programming in Javascript?

(I should note, I'm not asking about libraries that are focused on DOM-manipulation, AJAX, or user interface elements, like jQuery, Prototype, Mootools, ExtJS, etc.)

P.S. This a community wiki question.

October 29 2010

14:37

What are the Javascript libraries you depend on?

I'm getting back into "real programming(tm)" with Javascript, after years of reaching for it only when I needed to manipulate a web page in the browser. As I dive back in, I'm stumbling on some great libraries, like Underscore.js (developed by the folks at DocumentCloud), persistence.js, and require.js, which make aspects of writing large programs in Javascript easier or faster.

So, I'm wondering what other libraries are out there that I should look at? What are the libraries that you rely on every day when programming in Javascript?

(I should note, I'm not asking about libraries that are focused on DOM-manipulation, AJAX, or user interface elements, like jQuery, Prototype, Mootools, ExtJS, etc.)

P.S. This a community wiki question.

October 23 2010

00:28

Which scripting language for a novice who wants to get into Google/Bing Mapping APIs?

I have a journo background, and am a programming novice (except for a single undergad PASCAL course in 1994). My goal is to learn how to use the Google and/or Bing Maps APIs, but first, to get a handle on a scripting language like Java or Python. My question: a) Which of these languages is most useful in the context of a Maps API.

From what I've read, Python is a great language to get started with for a novice programmer, but when I read about the Google Maps API, a knowledge of Java always seems assumed. Is Java needed for working with Google Maps API? With Bing Maps' API? Can either of these APIs adapt to different scripts? As you can see, I'm a little confused.

Thanks in advance.

September 21 2010

13:09

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 already get your copy of the Smashing Book?]

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)
Tweet


© 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: javascript, jquery

September 13 2010

23:18

How Do I Make An Animated Menu?

Hi all,

I'd like to make an animated menu exactly like the one one this page: http://elections.nytimes.com/2010/senate/illinois

Click on "Other Senate Races."

I assume it has to be done in jQuery, but that's it. I took a look at the page in Firebug but it's way over my head.

I have no idea how to start.

There's an added twist to this, which is that this trick will need to be integrated into wordpress navbar.

The whole thing is generated in php, you can easily edit what the navbar displays in the wordpress backend.

June 22 2010

03:39

How many browsers do you test in?

And how do you do it?

This is rather haphazard for me. I have four browsers on my computer between OS X and XP on Parallels, so I test in those. Other editors and reporters involved in each project have different browsers so they report back any issues in them.

It's sporadic though and inconsistent. The last project I worked on, we discovered a javascript bug that only manifested itself in Firefox version 3.0.19 (and possibly others) and completely broke the graphic. Took quite a while to fix it.

Do people have like a set of computers with a whole bunch of different browsers installed as test computers or something?

Browser shots works well for layouts, but what about javascript interactions?

March 10 2010

14:40

What We're Reading

It's time for another roundup of links from NYT developers and Open blog readers. This week features lots of JavaScript-oriented links (not that there's anything wrong with that).

February 02 2010

14:49

Hacks and Hackers play with data-driven news

Last Friday’s London-based Hacks and Hacker’s Day, run by ScraperWiki (a new data tool set to launch in beta soon), provided some excellent inspiration for journalists and developers alike.

In groups, the programmers and journalists paired up to combine journalistic and data knowledge, resulting in some innovative projects: a visualisation showing the average profile of Conservative candidates standing in safe seats for the General Election (the winning project); graphics showing the most common words used for each horoscope sign; and an attempt to tackle the various formats used by data.gov.uk.

One of the projects, ‘They Write For You’ was an attempt to illustrate the political mix of articles by MPs for British newspapers and broadcasters. Using byline data combined with MP name data, the journalists and developers created this pretty mashup, which can be viewed at this link.

The team took the 2008-2010 data from Journalisted and used ScraperWiki, Python, Ruby and JavaScript to create the visualisation: each newspaper shows a byline breakdown by party. By hovering over a coloured box, users can see which MPs wrote for which newspaper over the same two year period.

The exact statistics, however, should be treated with some caution, as the information has not yet been cross-checked with other data sets.  It would appear, for example, that the Guardian newspaper published more stories by MPs than any other title, but this could be that Journalisted holds more information about the Guardian than its counterparts.

While this analysis is not yet ready to be transformed into a news story, it shows the potential for employing data skills to identify media and political trends.

Similar Posts:



January 19 2010

19:24
Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
Could not load more posts
Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
Just a second, loading more posts...
You've reached the end.

Don't be the product, buy the product!

Schweinderl