{"rowid": 164, "title": "My Other Christmas Present Is a Definition List", "contents": "A note from the editors: readers should note that the HTML5 redefinition of definition lists has come to pass and is now \u00e0 la mode.\n \n \n \n Last year, I looked at how the markup for tag clouds was generally terrible. I thought this year I would look not at a method of marking up a common module, but instead just at a simple part of HTML and how it generally gets abused.\n\nNo, not tables. Definition lists. Ah, definition lists. Often used but rarely understood.\n\nExamining the definition of definitions\n\nTo start with, let\u2019s see what the HTML spec has to say about them.\n\n\n\tDefinition lists vary only slightly from other types of lists in that list items consist of two parts: a term and a description.\n\n\nThe canonical example of a definition list is a dictionary. Words can have multiple descriptions (even the word definition has at least five). Also, many terms can share a single definition (for example, the word colour can also be spelt color, but they have the same definition).\n\nExcellent, we can all grasp that. But it very quickly starts to fall apart. Even in the HTML specification the definition list is mis-used.\n\n\n\tAnother application of DL, for example, is for marking up dialogues, with each DT naming a speaker, and each DD containing his or her words.\n\n\nWrong. Completely and utterly wrong. This is the biggest flaw in the HTML spec, along with dropping support for the start attribute on ordered lists. \u201cWhy?\u201d, you may ask. Let me give you an example from Romeo and Juliet, act 2, scene 2.\n\n
Juliet
\n\t
Romeo!
\n
Romeo
\n\t
My niesse?
\n
Juliet
\n\t
At what o'clock tomorrow shall I send to thee?
\n
Romeo
\n\t
At the hour of nine.
\n\nNow, the problem here is that a given definition can have multiple descriptions (the DD). Really the dialog \u201cdescriptions\u201d should be rolled up under the terms, like so:\n\n
Juliet
\n\t
Romeo!
\n\t
At what o'clock tomorrow shall I send to thee?
\n
Romeo
\n\t
My niesse?
\n\t
At the hour of nine.
\n\nSuddenly the play won\u2019t make anywhere near as much sense. (If it\u2019s anything, the correct markup for a play is an ordered list of CITE and BLOCKQUOTE elements.)\n\nThis is the first part of the problem. That simple example has turned definition lists in everyone\u2019s mind from pure definitions to more along the lines of a list with pre-configured heading(s) and text(s).\n\nScreen reader, enter stage left.\n\nIn many screen readers, a simple definition list would be read out as \u201cdefinition term equals definition description\u201d. So in our play excerpt, Juliet equals Romeo! That\u2019s not right, either. But this also leads a lot of people astray with definition lists to believing that they are useful for key/value pairs.\n\nBehaviour and convention\n\nThe WHAT-WG have noticed the common mis-use of the DL, and have codified it into the new spec. In the HTML5 draft, a definition list is no longer a definition list.\n\n\n\tThe dl element introduces an unordered association list consisting of zero or more name-value groups (a description list). Each group must consist of one or more names (dt elements) followed by one or more values (dd elements).\n\n\nThey also note that the \u201cdl element is inappropriate for marking up dialogue, since dialogue is ordered\u201d. So for that example they have created a DIALOG (sic) element.\n\nStrange, then, that they keep DL as-is but instead refer to it an \u201cassociation list\u201d. They have not created a new AL element, and kept DL for the original purpose. They have chosen not to correct the usage or to create a new opportunity for increased specificity in our HTML, but to \u201cpave the cowpath\u201d of convention.\n\nHow to use a definition list\n\nGiven that everyone else is using a DL incorrectly, should we? Well, if they all jumped off a bridge, would you too? No, of course you wouldn\u2019t. We don\u2019t have HTML5 yet, so we\u2019re stuck with the existing semantics of HTML4 and XHTML1. Which means that:\n\n\n\tListing dialogue is not defining anything.\n\tListing the attributes of a piece of hardware (resolution = 1600\u00d71200) is illustrating sample values, not defining anything (however, stating what \u2018resolution\u2019 actually means in this context would be a definition).\n\tListing the cast and crew of a given movie is not defining the people involved in making movies. (Stuart Gordon may have been the director of Space Truckers, but that by no means makes him the true definition of a director.)\n\tA menu of navigation items is simply a nested ordered or unordered list of links, not a definition list.\n\tApplying styling handles to form labels and elements is not a good use for a definition list.\n\n\nAnd so on.\n\nLiving by the specification, a definition list should be used for term definitions \u2013 glossaries, lexicons and dictionaries \u2013 only.\n\nAnything else is a crime against markup.", "year": "2007", "author": "Mark Norman Francis", "author_slug": "marknormanfrancis", "published": "2007-12-05T00:00:00+00:00", "url": "https://24ways.org/2007/my-other-christmas-present-is-a-definition-list/", "topic": "code"} {"rowid": 161, "title": "Keeping JavaScript Dependencies At Bay", "contents": "As we are writing more and more complex JavaScript applications we run into issues that have hitherto (god I love that word) not been an issue. The first decision we have to make is what to do when planning our app: one big massive JS file or a lot of smaller, specialised files separated by task. \n\nPersonally, I tend to favour the latter, mainly because it allows you to work on components in parallel with other developers without lots of clashes in your version control. It also means that your application will be more lightweight as you only include components on demand.\n\nStarting with a global object\n\nThis is why it is a good plan to start your app with one single object that also becomes the namespace for the whole application, say for example myAwesomeApp:\n\nvar myAwesomeApp = {};\n\nYou can nest any necessary components into this one and also make sure that you check for dependencies like DOM support right up front.\n\nAdding the components\n\nThe other thing to add to this main object is a components object, which defines all the components that are there and their file names.\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t}\n};\n\nTechnically you can also omit the loaded properties, but it is cleaner this way. The next thing to add is an addComponent function that can load your components on demand by adding new SCRIPT elements to the head of the documents when they are needed.\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t},\n\taddComponent:function(component){\n\t\tvar c = this.components[component];\n\t\tif(c && c.loaded === false){\n\t\t\tvar s = document.createElement('script');\n\t\t\ts.setAttribute('type', 'text/javascript');\n\t\t\ts.setAttribute('src',c.url);\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s);\n\t\t}\n\t}\n};\n\nThis allows you to add new components on the fly when they are not defined:\n\nif(!myAwesomeApp.components.gallery.loaded){\n\tmyAwesomeApp.addComponent('gallery');\n};\n\nVerifying that components have been loaded\n\nHowever, this is not safe as the file might not be available. To make the dynamic adding of components safer each of the components should have a callback at the end of them that notifies the main object that they indeed have been loaded:\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t},\n\taddComponent:function(component){\n\t\tvar c = this.components[component];\n\t\tif(c && c.loaded === false){\n\t\t\tvar s = document.createElement('script');\n\t\t\ts.setAttribute('type', 'text/javascript');\n\t\t\ts.setAttribute('src',c.url);\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s);\n\t\t}\n\t},\n\tcomponentAvailable:function(component){\n\t\tthis.components[component].loaded = true;\n\t}\n}\n\nFor example the gallery.js file should call this notification as a last line:\n\nmyAwesomeApp.gallery = function(){\n\t// [... other code ...]\n}();\nmyAwesomeApp.componentAvailable('gallery');\n\nTelling the implementers when components are available\n\nThe last thing to add (actually as a courtesy measure for debugging and implementers) is to offer a listener function that gets notified when the component has been loaded:\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t},\n\taddComponent:function(component){\n\t\tvar c = this.components[component];\n\t\tif(c && c.loaded === false){\n\t\t\tvar s = document.createElement('script');\n\t\t\ts.setAttribute('type', 'text/javascript');\n\t\t\ts.setAttribute('src',c.url);\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s);\n\t\t}\n\t},\n\tcomponentAvailable:function(component){\n\t\tthis.components[component].loaded = true;\n\t\tif(this.listener){\n\t\t\tthis.listener(component);\n\t\t};\n\t}\n};\n\nThis allows you to write a main listener function that acts when certain components have been loaded, for example:\n\nmyAwesomeApp.listener = function(component){\n\tif(component === 'gallery'){\n\t showGallery();\n\t}\n};\n\nExtending with other components\n\nAs the main object is public, other developers can extend the components object with own components and use the listener function to load dependent components. Say you have a bespoke component with data and labels in extra files:\n\nmyAwesomeApp.listener = function(component){\n\tif(component === 'bespokecomponent'){\n\t\tmyAwesomeApp.addComponent('bespokelabels');\n\t};\n\tif(component === 'bespokelabels'){\n\t\tmyAwesomeApp.addComponent('bespokedata');\n\t};\n\tif(component === 'bespokedata'){\n\t\tmyAwesomeApp,bespokecomponent.init();\n\t};\n};\nmyAwesomeApp.components.bespokecomponent = {\n\turl:'bespoke.js',\n\tloaded:false\n};\nmyAwesomeApp.components.bespokelabels = {\n\turl:'bespokelabels.js',\n\tloaded:false\n};\nmyAwesomeApp.components.bespokedata = {\n\turl:'bespokedata.js',\n\tloaded:false\n};\nmyAwesomeApp.addComponent('bespokecomponent');\n\nFollowing this practice you can write pretty complex apps and still have full control over what is available when. You can also extend this to allow for CSS files to be added on demand.\n\nInfluences\n\nIf you like this idea and wondered if someone already uses it, take a look at the Yahoo! User Interface library, and especially at the YAHOO_config option of the global YAHOO.js object.", "year": "2007", "author": "Christian Heilmann", "author_slug": "chrisheilmann", "published": "2007-12-18T00:00:00+00:00", "url": "https://24ways.org/2007/keeping-javascript-dependencies-at-bay/", "topic": "code"} {"rowid": 145, "title": "The Neverending (Background Image) Story", "contents": "Everyone likes candy for Christmas, and there\u2019s none better than eye candy. Well, that, and just more of the stuff. Today we\u2019re going to combine both of those good points and look at how to create a beautiful background image that goes on and on\u2026 forever!\n\nOf course, each background image is different, so instead of agonising over each and every pixel, I\u2019m going to concentrate on five key steps that you can apply to any of your own repeating background images. In this example, we\u2019ll look at the Miami Beach background image used on the new FOWA site, which I\u2019m afraid is about as un-festive as you can get.\n\n1. Choose your image wisely\n\nI find there are three main criteria when judging photos you\u2019re considering for repetition manipulation (or \u2018repetulation\u2019, as I like to say)\u2026\n\n\n\tsimplicity (beware of complex patterns)\n\tangle and perspective (watch out for shadows and obvious vanishing points)\n\tconsistent elements (for easy cloning)\n\n\nYou might want to check out this annotated version of the image, where I\u2019ve highlighted elements of the photo that led me to choose it as the right one.\n\nThe original image purchased from iStockPhoto.\n\nThe Photoshopped version used on the FOWA site.\n\n2. The power of horizontal lines\n\nWith the image chosen and your cursor poised for some Photoshop magic, the most useful thing you can do is drag out the edge pixels from one side of the image to create a kind of rough colour \u2018template\u2019 on which to work over. It doesn\u2019t matter which side you choose, although you might find it beneficial to use the one with the simplest spread of colour and complex elements.\n\nClick and hold on the marquee tool in the toolbar and select the \u2018single column marquee tool\u2019, which will span the full height of your document but will only be one pixel wide. Make the selection right at the edge of your document, press ctrl-c / cmd-c to copy the selection you made, create a new layer, and hit ctrl-v / cmd-v to paste the selection onto your new layer. using free transform (ctrl-t / cmd-t), drag out your selection so that it becomes as wide as your entire canvas. \n\nA one-pixel-wide selection stretched out to the entire width of the canvas.\n\n3. Cloning\n\nIt goes without saying that the trusty clone tool is one of the most important in the process of creating a seamlessly repeating background image, but I think it\u2019s important to be fairly loose with it. Always clone on to a new layer so that you\u2019ve got the freedom to move it around, but above all else, use the eraser tool to tweak your cloned areas: let that handle the precision stuff and you won\u2019t have to worry about getting your clones right first time.\n\nIn the example below, you can see how I overcame the problem of the far-left tree shadow being chopped off by cloning the shadow from the tree on its right. \n\nThe edge of the shadow is cut off and needs to be \u2018made\u2019 from a pre-existing element.\n\nThe successful clone completes the missing shadow.\n\nThe two elements are obviously very similar but it doesn\u2019t look like a clone because the majority of the shape is \u2018genuine\u2019 and only a small part is a duplicate. Also, after cloning I transformed the duplicate, erased parts of it, used gradients, and \u2014 ooh, did someone mention gradients?\n\n4. Never underestimate a gradient\n\nFor this image, I used gradients in a similar way to a brush: covering large parts of the canvas with a colour that faded out to a desired point, before erasing certain parts for accuracy.\n\nSeveral of the gradients and brushes that make up the \u2018customised\u2019 part of the image, visible when the main photograph layer is hidden.\n\nThe full composite.\n\nGradients are also a bit of an easy fix: you can use a gradient on one side of the image, flip it horizontally, and then use it again on the opposite side to make a more seamless join.\n\nSpeaking of which\u2026\n\n5. Sewing the seams\n\nNo matter what kind of magic Photoshop dust you sprinkle over your image, there will still always be the area where the two edges meet: that scary \u2018loop\u2019 point. Fret ye not, however, for there\u2019s help at hand in the form of a nice little cheat. Even though the loop point might still be apparent, we can help hide it by doing something to throw viewers off the scent.\n\nThe seam is usually easy to spot because it\u2019s a blank area with not much detail or colour variation, so in order to disguise it, go against the rule: put something across it!\n\nThis isn\u2019t quite as challenging as it may sound, because if we intentionally make our own \u2018object\u2019 to span the join, we can accurately measure the exact halfway point where we need to split it across the two sides of the image. This is exactly what I did with the FOWA background image: I made some clouds!\n\nA sky with no clouds in an unhappy one.\n\nA simple soft white brush creates a cloud-like formation in the sky.\n\nAfter taking the cloud\u2019s opacity down to 20%, I used free transform to highlight the boundaries of the layer. I then moved it over to the right, so that the middle of the layer perfectly aligned with the right side of the canvas.\n\nFinally, I duplicated the layer and did the same in reverse: dragging the layer over to the left and making sure that the middle of the duplicate layer perfectly aligned with the left side of the canvas.\n\nAnd there you have it! Boom! Ta-da! Et Voila! To see the repeating background image in action, visit futureofwebapps.com on a large widescreen monitor or see a simulation of the effect.\n\nThanks for reading, folks. Have a great Christmas!", "year": "2007", "author": "Elliot Jay Stocks", "author_slug": "elliotjaystocks", "published": "2007-12-03T00:00:00+00:00", "url": "https://24ways.org/2007/the-neverending-background-image-story/", "topic": "code"} {"rowid": 168, "title": "Unobtrusively Mapping Microformats with jQuery", "contents": "Microformats are everywhere. You can\u2019t shake an electronic stick these days without accidentally poking a microformat-enabled site, and many developers use microformats as a matter of course. And why not? After all, why invent your own class names when you can re-use pre-defined ones that give your site extra functionality for free?\n\nNevertheless, while it\u2019s good to know that users of tools such as Tails and Operator will derive added value from your shiny semantics, it\u2019s nice to be able to reuse that effort in your own code.\n\nWe\u2019re going to build a map of some of my favourite restaurants in Brighton. Fitting with the principles of unobtrusive JavaScript, we\u2019ll start with a semantically marked up list of restaurants, then use JavaScript to add the map, look up the restaurant locations and plot them as markers.\n\nWe\u2019ll be using a couple of powerful tools. The first is jQuery, a JavaScript library that is ideally suited for unobtrusive scripting. jQuery allows us to manipulate elements on the page based on their CSS selector, which makes it easy to extract information from microformats.\n\nThe second is Mapstraction, introduced here by Andrew Turner a few days ago. We\u2019ll be using Google Maps in the background, but Mapstraction makes it easy to change to a different provider if we want to later.\n\nGetting Started\n\nWe\u2019ll start off with a simple collection of microformatted restaurant details, representing my seven favourite restaurants in Brighton. The full, unstyled list can be seen in restaurants-plain.html. Each restaurant listing looks like this:\n\n
  • \n\t

    Riddle & Finns

    \n\t
    \n\t\t

    12b Meeting House Lane

    \n\t\t

    Brighton, UK

    \n\t\t

    BN1 1HB

    \n\t
    \n\t

    Telephone: +44 (0)1273 323 008

    \n\t

    E-mail: info@riddleandfinns.co.uk

    \n
  • \n\nSince we\u2019re dealing with a list of restaurants, each hCard is marked up inside a list item. Each restaurant is an organisation; we signify this by placing the classes fn and org on the element surrounding the restaurant\u2019s name (according to the hCard spec, setting both fn and org to the same value signifies that the hCard represents an organisation rather than a person).\n\nThe address information itself is contained within a div of class adr. Note that the HTML
    element is not suitable here for two reasons: firstly, it is intended to mark up contact details for the current document rather than generic addresses; secondly, address is an inline element and as such cannot contain the paragraphs elements used here for the address information.\n\nA nice thing about microformats is that they provide us with automatic hooks for our styling. For the moment we\u2019ll just tidy up the whitespace a bit; for more advanced style tips consult John Allsop\u2019s guide from 24 ways 2006.\n\n.vcard p {\n\tmargin: 0;\n}\n.adr {\n\tmargin-bottom: 0.5em;\n}\n\nTo plot the restaurants on a map we\u2019ll need latitude and longitude for each one. We can find this out from their address using geocoding. Most mapping APIs include support for geocoding, which means we can pass the API an address and get back a latitude/longitude point. Mapstraction provides an abstraction layer around these APIs which can be included using the following script tag:\n\n\n\nWhile we\u2019re at it, let\u2019s pull in the other external scripts we\u2019ll be using:\n\n\n\n\n\n\nThat\u2019s everything set up: let\u2019s write some JavaScript!\n\nIn jQuery, almost every operation starts with a call to the jQuery function. The function simulates method overloading to behave in different ways depending on the arguments passed to it. When writing unobtrusive JavaScript it\u2019s important to set up code to execute when the page has loaded to the point that the DOM is available to be manipulated. To do this with jQuery, pass a callback function to the jQuery function itself:\n\njQuery(function() {\n\t// This code will be executed when the DOM is ready\n});\n\nInitialising the map\n\nThe first thing we need to do is initialise our map. Mapstraction needs a div with an explicit width, height and ID to show it where to put the map. Our document doesn\u2019t currently include this markup, but we can insert it with a single line of jQuery code:\n\njQuery(function() {\n\t// First create a div to host the map\n\tvar themap = jQuery('
    ').css({\n\t\t'width': '90%',\n\t\t'height': '400px'\n\t}).insertBefore('ul.restaurants');\n});\n\nWhile this is technically just a single line of JavaScript (with line-breaks added for readability) it\u2019s actually doing quite a lot of work. Let\u2019s break it down in to steps:\n\nvar themap = jQuery('
    ')\n\nHere\u2019s jQuery\u2019s method overloading in action: if you pass it a string that starts with a < it assumes that you wish to create a new HTML element. This provides us with a handy shortcut for the more verbose DOM equivalent:\n\nvar themap = document.createElement('div');\nthemap.id = 'themap';\n\nNext we want to apply some CSS rules to the element. jQuery supports chaining, which means we can continue to call methods on the object returned by jQuery or any of its methods:\n\nvar themap = jQuery('
    ').css({\n\t'width': '90%',\n\t'height': '400px'\n})\n\nFinally, we need to insert our new HTML element in to the page. jQuery provides a number of methods for element insertion, but in this case we want to position it directly before the