{"database": "24ways", "rows": [[175, "Front-End Code Reusability with CSS and JavaScript", "Most web standards-based developers are more than familiar with creating their sites with semantic HTML with lots and lots of CSS. With each new page in a design, the CSS tends to grow and grow and more elements and styles are added. But CSS can be used to better effect.\n\nThe idea of object-oriented CSS isn\u2019t new. Nicole Sullivan has written a presentation on the subject and outlines two main concepts: separate structure and visual design; and separate container and content. Jeff Croft talks about Applying OOP Concepts to CSS:\n\n\n\tI can make a class of .box that defines some basic layout structure, and another class of .rounded that provides rounded corners, and classes of .wide and .narrow that define some widths, and then easily create boxes of varying widths and styles by assigning multiple classes to an element, without having to duplicate code in my CSS.\n\n\nThis concept helps reduce CSS file size, allows for great flexibility, rapid building of similar content areas and means greater consistency throughout the entire design. You can also take this concept one step further and apply it to site behaviour with JavaScript.\n\nBuild a versatile slideshow\n\nI will show you how to build multiple slideshows using jQuery, allowing varying levels of functionality which you may find on one site design. The code will be flexible enough to allow you to add previous/next links, image pagination and the ability to change the animation type. More importantly, it will allow you to apply any combination of these features.\n\nImage galleries are simply a list of images, so the obvious choice of marking the content up is to use a <ul>. Many designs, however, do not cater to non-JavaScript versions of the website, and thus don\u2019t take in to account large multiple images. You could also simply hide all the other images in the list, apart from the first image. This method can waste bandwidth because the other images might be downloaded when they are never going to be seen.\n\nTaking this second concept \u2014 only showing one image \u2014 the only code you need to start your slideshow is an <img> tag. The other images can be loaded dynamically via either a per-page JavaScript array or via AJAX.\n\nThe slideshow concept is built upon the very versatile Cycle jQuery Plugin and is structured in to another reusable jQuery plugin. Below is the HTML and JavaScript snippet needed to run every different type of slideshow I have mentioned above.\n\n<img src=\"path/to/image.jpg\" alt=\"About the image\" title=\"\" height=\"250\" width=\"400\" class=\"slideshow\">\n<script type=\"text/javascript\">\n\tjQuery().ready(function($) {\n\t\t$('img.slideshow').slideShow({\n\t\t\timages: ['1.jpg', '2.jpg', '3.jpg']\n\t\t});\n\t});\n</script>\n\nSlideshow plugin\n\nIf you\u2019re not familiar with jQuery or how to write and author your own plugin there are plenty of articles to help you out.\n\njQuery has a chainable interface and this is something your plugin must implement. This is easy to achieve, so your plugin simply returns the collection it is using:\n\nreturn this.each(\n\tfunction () {}\n};\n\nLocal Variables\n\nTo keep the JavaScript clean and avoid any conflicts, you must set up any variables which are local to the plugin and should be used on each collection item. Defining all your variables at the top under one statement makes adding more and finding which variables are used easier. For other tips, conventions and improvements check out JSLint, the \u201cJavaScript Code Quality Tool\u201d.\n\nvar $$, $div, $images, $arrows, $pager,\n\tid, selector, path, o, options,\n\theight, width,\n\tlist = [], li = 0,\n\tparts = [], pi = 0,\n\tarrows = ['Previous', 'Next'];\n\nCache jQuery Objects\n\nIt is good practice to cache any calls made to jQuery. This reduces wasted DOM calls, can improve the speed of your JavaScript code and makes code more reusable.\n\nThe following code snippet caches the current selected DOM element as a jQuery object using the variable name $$. Secondly, the plugin makes its settings available to the Metadata plugin\u2021 which is best practice within jQuery plugins.\n\nFor each slideshow the plugin generates a <div> with a class of slideshow and a unique id. This is used to wrap the slideshow images, pagination and controls.\n\nThe base path which is used for all the images in the slideshow is calculated based on the existing image which appears on the page. For example, if the path to the image on the page was /img/flowers/1.jpg the plugin would use the path /img/flowers/ to load the other images.\n\n$$ = $(this);\no = $.metadata ? $.extend({}, settings, $$.metadata()) : settings;\nid = 'slideshow-' + (i++ + 1);\n$div = $('<div />').addClass('slideshow').attr('id', id);\nselector = '#' + id + ' ';\npath = $$.attr('src').replace(/[0-9]\\.jpg/g, '');\noptions = {};\nheight = $$.height();\nwidth = $$.width();\n\nNote: the plugin uses conventions such as folder structure and numeric filenames. These conventions help with the reusable aspect of plugins and best practices.\n\nBuild the Images\n\nThe cycle plugin uses a list of images to create the slideshow. Because we chose to start with one image we must now build the list programmatically. This is a case of looping through the images which were added via the plugin options, building the appropriate HTML and appending the resulting <ul> to the DOM.\n\n$.each(o.images, function () {\n\tlist[li++] = '<li>';\n\tlist[li++] = '<img src=\"' + path + this + '\" height=\"' + height + '\" width=\"' + width + '\">';\n\tlist[li++] = '</li>';\n});\n$images = $('<ul />').addClass('cycle-images');\n$images.append(list.join('')).appendTo($div);\n\nAlthough jQuery provides the append method it is much faster to create one really long string and append it to the DOM at the end.\n\nUpdate the Options\n\nHere are some of the options we\u2019re making available by simply adding classes to the <img>. You can change the slideshow effect from the default fade to the sliding effect. By adding the class of stopped the slideshow will not auto-play and must be controlled via pagination or previous and next links.\n\n// different effect\nif ($$.is('.slide')) {\n\toptions.fx = 'scrollHorz';\n}\n// don't move by default\nif ($$.is('.stopped')) {\n\toptions.timeout = 0;\n}\n\nIf you are using the same set of images throughout a website you may wish to start on a different image on each page or section. This can be easily achieved by simply adding the appropriate starting class to the <img>.\n\n// based on the class name on the image\nif ($$.is('[class*=start-]')) {\n\toptions.startingSlide = parseInt($$.attr('class').replace(/.*start-([0-9]+).*/g, \"$1\"), 10) - 1;\n}\n\nFor example:\n\n<img src=\"/img/slideshow/3.jpg\" alt=\"About the image\" title=\"\" height=\"250\" width=\"400\" class=\"slideshow start-3\">\n\nBy default, and without JavaScript, the third image in this slideshow is shown. When the JavaScript is applied to the page the slideshow must know to start from the correct place, this is why the start class is required.\n\nYou could capture the default image name and parse it to get the position, but only the default image needs to be numeric to work with this plugin (and could easily be changed in future). Therefore, this extra specifically defined option means the plugin is more tolerant.\n\nPrevious/Next Links\n\nA common feature of slideshows is previous and next links enabling the user to manually progress the images. The Cycle plugin supports this functionality, but you must generate the markup yourself. Most people add these directly in the HTML but normally only support their behaviour when JavaScript is enabled. This goes against progressive enhancement. To keep with the best practice progress enhancement method the previous/next links should be generated with JavaScript.\n\nThe follow snippet checks whether the slideshow requires the previous/next links, via the arrows class. It restricts the Cycle plugin to the specific slideshow using the selector we created at the top of the plugin. This means multiple slideshows can run on one page without conflicting each other.\n\nThe code creates a <ul> using the arrows array we defined at the top of the plugin. It also adds a class to the slideshow container, meaning you can style different combinations of options in your CSS.\n\n// create the arrows\nif ($$.is('.arrows') && list.length > 1) {\n\toptions.next = selector + '.next';\n\toptions.prev = selector + '.previous';\n\t$arrows = $('<ul />').addClass('cycle-arrows');\n\t$.each(arrows, function (i, val) {\n\t\tparts[pi++] = '<li class=\"' + val.toLowerCase() + '\">';\n\t\tparts[pi++] = '<a href=\"#' + val.toLowerCase() + '\">';\n\t\tparts[pi++] = '<span>' + val + '</span>';\n\t\tparts[pi++] = '</a>';\n\t\tparts[pi++] = '</li>';\n\t});\n\t$arrows.append(parts.join('')).appendTo($div);\n\t$div.addClass('has-cycle-arrows');\n}\n\nThe arrow array could be placed inside the plugin settings to allow for localisation.\n\nPagination\n\nThe Cycle plugin creates its own HTML for the pagination of the slideshow. All our plugin needs to do is create the list and selector to use. This snippet creates the pagination container and appends it to our specific slideshow container. It sets the Cycle plugin pager option, restricting it to the specific slideshow using the selector we created at the top of the plugin. Like the previous/next links, a class is added to the slideshow container allowing you to style the slideshow itself differently.\n\n// create the clickable pagination\nif ($$.is('.pagination') && list.length > 1) {\n\toptions.pager = selector + '.cycle-pagination';\n\t$pager = $('<ul />').addClass('cycle-pagination');\n\t$pager.appendTo($div);\n\t$div.addClass('has-cycle-pagination');\n}\n\nNote: the Cycle plugin creates a <ul> with anchors listed directly inside without the surrounding <li>. Unfortunately this is invalid markup but the code still works.\n\nDemos\n\nWell, that describes all the ins-and-outs of the plugin, but demos make it easier to understand! Viewing the source on the demo page shows some of the combinations you can create with a simple <img>, a few classes and some thought-out JavaScript.\n\nView the demos \u2192\n\nDecide on defaults\n\nThe slideshow plugin uses the exact same settings as the Cycle plugin, but some are explicitly set within the slideshow plugin when using the classes you have set.\n\nWhen deciding on what functionality is going to be controlled via this class method, be careful to choose your defaults wisely. If all slideshows should auto-play, don\u2019t make this an option \u2014 make the option to stop the auto-play. Similarly, if every slideshow should have previous/next functionality make this the default and expose the ability to remove them with a class such as \u201cno-pagination\u201d.\n\nIn the examples presented on this article I have used a class on each <img>. You can easily change this to anything you want and simply apply the plugin based on the jQuery selector required.\n\nGrab your images\n\nIf you are using AJAX to load in your images, you can speed up development by deciding on and keeping to a folder structure and naming convention. There are two methods: basing the image path based on the current URL; or based on the src of the image. The first allows a different slideshow on each page, but in many instances a site will have a couple of sets of images and therefore the second method is probably preferred.\n\nMetadata \u2021\n\nA method which allows you to directly modify settings in certain plugins, which also uses the classes from your HTML already exists. This is a jQuery plugin called Metadata. This method allows for finer control over the plugin settings themselves. Some people, however, may dislike the syntax and prefer using normal classes, like above which when sprinkled with a bit more JavaScript allows you to control what you need to control.\n\nThe takeaway\n\nHopefully you have understood not only what goes in to a basic jQuery plugin but also learnt a new and powerful idea which you can apply to other areas of your website.\n\nThe idea can also be applied to other common interfaces such as lightboxes or mapping services such as Google Maps \u2014 for example creating markers based on a list of places, each with different pin icons based the anchor class.", "2009", "Trevor Morris", "trevormorris", "2009-12-06T00:00:00+00:00", "https://24ways.org/2009/front-end-code-reusability-with-css-and-javascript/", "code"]], "truncated": false, "columns": ["rowid", "title", "contents", "year", "author", "author_slug", "published", "url", "topic"], "query": {"sql": "select rowid, * from articles where \"author\" = :p0 and \"year\" = :p1 order by rowid limit 101", "params": {"p0": "Trevor Morris", "p1": "2009"}}, "query_ms": 1.7266273498535156}