{"rowid": 124, "title": "Writing Responsible JavaScript", "contents": "Without a doubt, JavaScript has been making something of a comeback in the last year. If you\u2019re involved in client-side development in any way at all, chances are that you\u2019re finding yourself writing more JavaScript now than you have in a long time.\n\nIf you learned most of your JavaScript back when DHTML was all the rage and before DOM Scripting was in vogue, there have been some big shifts in the way scripts are written. Most of these are in the way event handlers are assigned and functions declared. Both of these changes are driven by the desire to write scripts that are responsible page citizens, both in not tying behaviour to content and in taking care not to conflict with other scripts. I thought it may be useful to look at some of these more responsible approaches to learn how to best write scripts that are independent of the page content and are safely portable between different applications.\n\nEvent Handling\n\nBack in the heady days of Web 1.0, if you wanted to have an object on the page react to something like a click, you would simply go ahead and attach an onclick attribute. This was easy and understandable, but much like the font tag or the style attribute, it has the downside of mixing behaviour or presentation in with our content. As we\u2019re learned with CSS, there are big benefits in keeping those layers separate. Hey, if it works for CSS, it should work for JavaScript too.\n\nJust like with CSS, instead of adding an attribute to our element within the document, the more responsible way to do that is to look for the item from your script (like CSS does with a selector) and then assign the behaviour to it. To give an example, take this oldskool onclick use case:\n\nPlay the animation\n\nThis could be rewritten by removing the onclick attribute, and instead doing the following from within your JavaScript.\n\ndocument.getElementById('anim-link').onclick = playAnimation;\n\nIt\u2019s all in the timing\n\nOf course, it\u2019s never quite that easy. To be able to attach that onclick, the element you\u2019re targeting has to exist in the page, and the page has to have finished loading for the DOM to be available. This is where the onload event is handy, as it fires once everything has finished loading. Common practise is to have a function called something like init() (short for initialise) that sets up all these event handlers as soon as the page is ready.\n\nBack in the day we would have used the onload attibute on the element to do this, but of course what we really want is:\n\nwindow.onload = init;\n\nAs an interesting side note, we\u2019re using init here rather than init() so that the function is assigned to the event. If we used the parentheses, the init function would have been run at that moment, and the result of running the function (rather than the function itself) would be assigned to the event. Subtle, but important.\n\nAs is becoming apparent, nothing is ever simple, and we can\u2019t just go around assigning our initialisation function to window.onload. What if we\u2019re using other scripts in the page that might also want to listen out for that event? Whichever script got there last would overwrite everything that came before it. To manage this, we need a script that checks for any existing event handlers, and adds the new handler to it. Most of the JavaScript libraries have their own systems for doing this. If you\u2019re not using a library, Simon Willison has a good stand-alone example\n\nfunction addLoadEvent(func) {\n\tvar oldonload = window.onload;\n\tif (typeof window.onload != 'function') {\n\t\twindow.onload = func;\n\t} else {\n\t\twindow.onload = function() {\n\t\t\tif (oldonload) {\n\t\t\t\toldonload();\n\t\t\t}\n\t\t\tfunc();\n\t\t}\n\t}\n}\n\nObviously this is just a toe in the events model\u2019s complex waters. Some good further reading is PPK\u2019s Introduction to Events.\n\nCarving out your own space\n\nAnother problem that rears its ugly head when combining multiple scripts on a single page is that of making sure that the scripts don\u2019t conflict. One big part of that is ensuring that no two scripts are trying to create functions or variables with the same names. Reusing a name in JavaScript just over-writes whatever was there before it.\n\nWhen you create a function in JavaScript, you\u2019ll be familiar with doing something like this.\n\nfunction foo() {\n\t... goodness ...\n}\n\nThis is actually just creating a variable called foo and assigning a function to it. It\u2019s essentially the same as the following.\n\nvar foo = function() {\n\t... goodness ...\n}\n\nThis name foo is by default created in what\u2019s known as the \u2018global namespace\u2019 \u2013 the general pool of variables within the page. You can quickly see that if two scripts use foo as a name, they will conflict because they\u2019re both creating those variables in the global namespace.\n\nA good solution to this problem is to add just one name into the global namespace, make that one item either a function or an object, and then add everything else you need inside that. This takes advantage of JavaScript\u2019s variable scoping to contain you mess and stop it interfering with anyone else.\n\nCreating An Object\n\nSay I was wanting to write a bunch of functions specifically for using on a site called \u2018Foo Online\u2019. I\u2019d want to create my own object with a name I think is likely to be unique to me.\n\nvar FOOONLINE = {};\n\nWe can then start assigning functions are variables to it like so:\n\nFOOONLINE.message = 'Merry Christmas!';\nFOOONLINE.showMessage = function() {\n\talert(this.message);\n};\n\nCalling FOOONLINE.showMessage() in this example would alert out our seasonal greeting. The exact same thing could also be expressed in the following way, using the object literal syntax.\n\nvar FOOONLINE = {\n\tmessage: 'Merry Christmas!',\n\tshowMessage: function() {\n\t\talert(this.message);\n\t}\n};\n\nCreating A Function to Create An Object\n\nWe can extend this idea bit further by using a function that we run in place to return an object. The end result is the same, but this time we can use closures to give us something like private methods and properties of our object.\n\nvar FOOONLINE = function(){\n\tvar message = 'Merry Christmas!';\n\treturn {\n\t\tshowMessage: function(){\n\t\t\talert(message);\n\t\t}\n\t}\n}();\n\nThere are two important things to note here. The first is the parentheses at the end of line 10. Just as we saw earlier, this runs the function in place and causes its result to be assigned. In this case the result of our function is the object that is returned at line 4.\n\nThe second important thing to note is the use of the var keyword on line 2. This ensures that the message variable is created inside the scope of the function and not in the global namespace. Because of the way closure works (which if you\u2019re not familiar with, just suspend your disbelief for a moment) that message variable is visible to everything inside the function but not outside. Trying to read FOOONLINE.message from the page would return undefined.\n\nThis is useful for simulating the concept of private class methods and properties that exist in other programming languages. I like to take the approach of making everything private unless I know it\u2019s going to be needed from outside, as it makes the interface into your code a lot clearer for someone else to read. \n\nAll Change, Please\n\nSo that was just a whistle-stop tour of a couple of the bigger changes that can help to make your scripts better page citizens. I hope it makes useful Sunday reading, but obviously this is only the tip of the iceberg when it comes to designing modular, reusable code.\n\nFor some, this is all familiar ground already. If that\u2019s the case, I encourage you to perhaps submit a comment with any useful resources you\u2019ve found that might help others get up to speed. Ultimately it\u2019s in all of our interests to make sure that all our JavaScript interoperates well \u2013 share your tips.", "year": "2006", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2006-12-10T00:00:00+00:00", "url": "https://24ways.org/2006/writing-responsible-javascript/", "topic": "code"} {"rowid": 144, "title": "The Mobile Web, Simplified", "contents": "A note from the editors: although eye-opening in 2006, this article is no longer relevant to today\u2019s mobile web.\n \n \n \n Considering a foray into mobile web development? Following are four things you need to know before making the leap.\n\n1. 4 billion mobile subscribers expected by 2010\n\nFancy that. Coupled with the UN prediction of 6.8 billion humans by 2010, 4 billion mobile subscribers (source) is an astounding 59% of the planet. Just how many of those subscribers will have data plans and web-enabled phones is still in question, but inevitably this all means one thing for you and me: A ton of potential eyes to view our web content on a mobile device.\n\n2. Context is king\n\nYour content is of little value to users if it ignores the context in which it is viewed. Consider how you access data on your mobile device. You might be holding a bottle of water or gripping a handle on the subway/tube. You\u2019re probably seeking specific data such as directions or show times, rather than the plethora of data at your disposal via a desktop PC.\n\nThe mobile web, a phrase often used to indicate \u201caccessing the web on a mobile device\u201d, is very much a context-, content-, and component-specific environment. Expressed in terms of your potential target audience, access to web content on a mobile device is largely influenced by surrounding circumstances and conditions, information relevant to being mobile, and the feature set of the device being used. Ask yourself, What is relevant to my users and the tasks, problems, and needs they may encounter while being mobile? Answer that question and you\u2019ll be off to a great start.\n\n3. WAP 2.0 is an XHTML environment\n\nIn a nutshell, here are a few fundamental tenets of mobile internet technology:\n\n\n\tWireless Application Protocol (WAP) is the protocol for enabling mobile access to internet content.\n\tWireless Markup Language (WML) was the language of choice for WAP 1.0.\n\tNearly all devices sold today are WAP 2.0 devices.\n\tWith the introduction of WAP 2.0, XHTML Mobile Profile (XHTML-MP) became the preferred markup language.\n\tXHTML-MP will be familiar to anyone experienced with XHTML Transitional or Strict.\n\n\nSummary? The mobile web is rapidly becoming an XHTML environment, and thus you and I can apply our existing \u201cdesktop web\u201d skills to understand how to develop content for it. With WML on the decline, the learning curve is much smaller today than it was several years ago. I\u2019m generalizing things gratuitously, but the point remains: Get off yo\u2019 lazy butt and begin to take mobile seriously.\n\nI\u2019ll even pass you a few tips for getting started. First, the DOCTYPE for XHTML-MP is as follows:\n\n\n\nAs for MIME type, Open Mobile Alliance (OMA) specifies using the MIME type application/vnd.wap.xhtml+xml, but ultimately you need to ensure the server delivering your mobile content is configured properly for the MIME type you choose to use, as there are other options (see Setting up WAP Servers).\n\nOnce you\u2019ve made it to the body, the XHTML-MP markup is not unlike what you\u2019re already used to. A few resources worth skimming:\n\n\n\tDevelopers Home XHTML-MP Tutorial \u2013 An impressively replete resource for all things XHTML-MP\n\tXHTML-MP Tags List \u2013 A complete list of XHTML-MP elements and accompanying attributes\n\n\nAnd last but certainly not least, CSS. There exists WAP CSS, which is essentially a subset of CSS2 with WAP-specific extensions. For all intents and purposes, much of the CSS you\u2019re already comfortable using will be transferrable to mobile. As for including CSS in your pages, your options are the same as for desktop sites: external, embedded, and inline. Some experts will argue embedded or inline over external in favor of reducing the number of HTTP connections per page request, yet many popular mobilized sites and apps employ external linking without issue.\n\nStocking stuffers: Flickr Mobile, Fandango Mobile, and Popurls Mobile. A few sites with whom you can do the View Source song and dance for further study.\n\n4. \u201cCell phone\u201d is so DynaTAC\n\nIf you\u2019re a U.S. resident, listen up: You must rid your vocabulary of the term \u201ccell phone\u201d. We\u2019re one of the few economies on the planet to refer to a mobile phone accordingly. If you care to find yourself in any of the worthwhile mobile development circles, begin using terms more widely accepted: \u201cmobile\u201d or \u201cmobile phone\u201d or \u201chandset\u201d or \u201chandy\u201d. If you\u2019re not sure which, go for \u201cmobile\u201d. Such as, \u201cYo dog, check out my new mobile.\u201d\n\nMore importantly, however, is overcoming the mentality that access to the mobile web can be done only with a phone. Instead, \u201cdevice\u201d encourages us to think phone, handheld computer, watch, Nintendo DS, car, you name it.\n\nSimple enough?", "year": "2006", "author": "Cameron Moll", "author_slug": "cameronmoll", "published": "2006-12-19T00:00:00+00:00", "url": "https://24ways.org/2006/the-mobile-web-simplified/", "topic": "ux"} {"rowid": 132, "title": "Tasty Text Trimmer", "contents": "In most cases, when designing a user interface it\u2019s best to make a decision about how data is best displayed and stick with it. Failing to make a decision ultimately leads to too many user options, which in turn can be taxing on the poor old user. \n\nUnder some circumstances, however, it\u2019s good to give the user freedom in customising their workspace. One good example of this is the \u2018Article Length\u2019 tool in Apple\u2019s Safari RSS reader. Sliding a slider left of right dynamically changes the length of each article shown. It\u2019s that kind of awesomey magic stuff that\u2019s enough to keep you from sleeping. Let\u2019s build one.\n\nThe Setup\n\nLet\u2019s take a page that has lots of long text items, a bit like a news page or like Safari\u2019s RSS items view. If we were to attach a class name to each element we wanted to resize, that would give us something to hook onto from the JavaScript. \n\nExample 1: The basic page.\n\nAs you can see, I\u2019ve wrapped my items in a DIV and added a class name of chunk to them. It\u2019s these chunks that we\u2019ll be finding with the JavaScript. Speaking of which \u2026\n\nOur Core Functions\n\nThere are two main tasks that need performing in our script. The first is to find the chunks we\u2019re going to be resizing and store their original contents away somewhere safe. We\u2019ll need this so that if we trim the text down we\u2019ll know what it was if the user decides they want it back again. We\u2019ll call this loadChunks. \n\nvar loadChunks = function(){\n\tvar everything = document.getElementsByTagName('*');\n\tvar i, l;\n\tchunks\t= [];\n\tfor (i=0, l=everything.length; i -1){\n\t\t\tchunks.push({\n\t\t\t\tref: everything[i],\n\t\t\t\toriginal: everything[i].innerHTML\n\t\t\t});\n\t\t}\n\t}\n};\n\nThe variable chunks is stored outside of this function so that we can access it from our next core function, which is doTrim.\n\nvar doTrim = function(interval) {\n\tif (!chunks) loadChunks();\n\tvar i, l;\n\tfor (i=0, l=chunks.length; i\n\t

Web Directions North\n\t\t\n\t\t\t\"download\n\t

\n\n\t\n\t\t 1485 Laperri\u00e8re Avenue \n\t\t Ottawa ON K1Z 7S8 \n\t\tCanada\n\t\n\n\t\n\t\tPhone/Fax: Work: 61 2 9365 5007\n\t\tEmail: info@webdirections.org\n\t\n\n\nWe\u2019ll be using a variation on the now well established \u201csliding doors\u201d technique (if you create a CSS technique, remember it\u2019s very important to give it a memorable name or acronym, and bonus points if you get your name in there!) by Douglas Bowman, enhanced by Scott Schiller (see http://www.schillmania.com/projects/dialog/,) which will give us a design which looks like this\n\n\n\nThe technique, in a nutshell, uses background images on four elements, two at the top, and two at the bottom, to add each rounded corner.\n\nWe are going to make this design \u201cfluid\u201d in the sense that it grows and shrinks in proportion with the size of the font that the text of the element is displayed with. This is sometimes referred to as an \u201cem driven design\u201d (we\u2019ll see why in a moment).\n\nTo see how this works in practice, here\u2019s the same design with the text \u201czoomed\u201d up in size\n\n\n\nand the same design again, when we zoom the text size down\n\n\n\nBy the way, the hCard image comes from Chris Messina, and you can download it and other microformat icons from the microformats wiki.\n\nNow, with CSS3, this whole task would be considerably easier, because we can add multiple background images to an element, and border images for each edge of an element. Safari, version 1.3 up, actually supports multiple background images, but sadly, it\u2019s not supported in Firefox 1.5, or even Firefox 2.0 (let\u2019s not mention IE7 eh?). So it\u2019s probably too little supported to use now. So instead we\u2019ll use a technique that only involves CSS2, and works in pretty much any browser.\n\nVery often, developers add div or span elements as containers for these background images, and in fact, if you visit Scott Shiller\u2019s site, that\u2019s what he has done there. But if at all possible we shouldn\u2019t be adding any HTML simply for presentational purposes, even if the presentation is done via CSS. What we can do is to use the HTML we have already, as much as is possible, to add the style we want. This can take some creative thinking, but once you get the hang of this approach it becomes a more natural way of using HTML compared with simply adding divs and spans at will as hooks for style. Of course, this technique isn\u2019t always simple, and in fact sometimes simply not possible, requiring us to add just a little HTML to provide the \u201chooks\u201d for CSS.\n\nLet\u2019s go to work\n\nThe first step is to add a background image to the whole vCard element.\n\n\n\nWe make this wide enough (for example 1000 or more pixels) and tall enough that no matter how large the content of the vCard grows, it will never overflow this area. We can\u2019t simply repeat the image, because the top left corner will show when the image repeats.\n\nWe add this as the background image of the vCard element using CSS.\n\nWhile we are at it, let\u2019s give the text a sans-serif font, some color so that it will be visible, and stop the image repeating.\n\n.vcard {\n\tbackground-image: url(images/vcardfill.png);\n\tbackground-repeat: no-repeat;\n\tcolor: #666;\n\tfont-family: \"Lucida Grande\", Verdana, Helvetica, Arial, sans-serif;\n}\n\nWhich in a browser, will look something like this.\n\n\n\nNext step we need to add the top right hand corner of the hCard. In keeping with our aim of not adding HTML simply for styling purposes, we want to use the existing structure of the page where possible. Here, we\u2019ll use the paragraph of class fn and org, which is the first child element of the vcard element.\n\n

Web Directions Conference Pty Ltd \"download

\n\nHere\u2019s our CSS for this element\n\n.fn {\n\tbackground-image: url(images/topright.png);\n\tbackground-repeat: no-repeat;\n\tbackground-position: top right;\n\tpadding-top: 2em;\n\tfont-weight: bold;\n\tfont-size: 1.1em;\n}\n\nAgain, we don\u2019t want it to repeat, but this time, we\u2019ve specified a background position for the image. This will make the background image start from the top, but its right edge will be located at the right edge of the element. I also made the font size a little bigger, and the weight bold, to differentiate it from the rest of the text in the hCard.\n\nHere\u2019s the image we are adding as the background to this element.\n\n\n\nSo, putting these two CSS statements together we get\n\n\n\nWe specified a padding-top of 2em to give some space between the content of the fn element and the edge of the fn element. Otherwise the top of the hCard image would be hard against the border. To see this in action, just remove the padding-top: 2em; declaration and preview in a browser.\n\nSo, with just two statements, we are well under way. We\u2019ve not even had to add any HTML so far. Let\u2019s turn to the bottom of the element, and add the bottom border (well, the background image which will serve as that border).\n\nNow, which element are we going to use to add this background image to?\n\nOK, here I have to admit to a little, teensie bit of cheating. If you look at the HTML of the hCard, I\u2019ve grouped the email and telephone properties into a div, with a class of telecommunications. This grouping is not strictly requred for our hCard.\n\n
\n\t

Phone/Fax: Work:\n\t\t61 2 9365 5007

\n\t

Email: info@webdirections.org

\n
\n\nNow, I chose that class name because that is what the vCard specification calls this group of properties. And typically, I do tend to group together related elements using divs when I mark up content. I find it makes the page structure more logical and readable. But strictly speaking, this isn\u2019t necessary, so you may consider it cheating. But my lesson in this would be, if you are going to add markup, try to make it as meaningful as possible.\n\nAs you have probably guessed by now, we are going to add one part of the bottom border image to this element. We\u2019re going to add this image as the background-image.\n\n\n\nAgain, it will be a very wide image, like the top left one, so that no matter how wide the element might get, the background image will still be wide enough. Now, we\u2019ll need to make this image sit in the bottom left of the element we attach it to, so we use a backgound position of left bottom (we put the horizontal position before the vertical). Here\u2019s our CSS statement for this\n\n.telecommunications {\n\tbackground-image: url(images/bottom-left.png);\n\tbackground-repeat: no-repeat;\n\tbackground-position: left bottom;\n\tmargin-bottom: 2em;\n}\n\nAnd that will look like this\n\n\n\nNot quite there, but well on the way. Time for the final piece in the puzzle.\n\nOK, I admit, I might have cheated just a little bit more in this step. But like the previous step, all valid, and (hopefully) quite justifiable markup. If we look at the HTML again, you\u2019ll find that our email address is marked up like this\n\n

Email: info@webdirections.org

\n\nTypically, in hCard, the value part of this property isn\u2019t required, and we could get away with\n\ninfo@webdirections.org\n\nThe form I\u2019ve used, with the span of class value is however, perfectly valid hCard markup (hard allows for multiple email addresses of different types, which is where this typically comes in handy). Why have I gone to all this trouble? Well, when it came to styling the hCard, I realized I needed a block element to attach the background image for the bottom right hand corner to. Typically the last block element in the containing element is the ideal choice (and sometimes it\u2019s possible to take an inline element, for example the link here, and use CSS to make it a block element, and attach it to that, but that really doesn\u2019t work with this design).\n\nSo, if we are going to use the paragraph which contains the email link, we need a way to select it exclusively, which means that with CSS2 at least, we need a class or id as a hook for our CSS selector (in CSS3 we could use the last-child selector, which selects the last child element of a specified element, but again, as last child is not widely supported, we won\u2019t rely on it here.)\n\nSo, the least worst thing we could do is take an existing element, and add some reasonably meaningful markup to it. That\u2019s why we gave the paragraph a class of email, and the email address a class of value. Which reminds me a little of a moment in Hamlet\n\n\n\tThe lady doth protest too much, methinks\n\n\nOK, let\u2019s get back to the CSS.\n\nWe add the bottom right corner image, positioning it in the bottom right of the element, and making sure it doesn\u2019t repeat. We also add some padding to the bottom, to balance out the padding we added to the top of the hCard.\n\np.email {\n\tbackground-image: url(images/bottom-right.png);\n\tbackground-position: right bottom;\n\tbackground-repeat: no-repeat;\n\tpadding-bottom: 2em;\n}\n\nWhich all goes to make our hCard look like this\n\n\n\nIt just remains for us to clean up a little.\n\nLet\u2019s start from the top. We\u2019ll float the download image to the right like this\n\n.vcard img {\n\tfloat: right;\n\tpadding-right: 1em;\n\tmargin-top: -1em\n}\n\nSee how we didn\u2019t have to add a class to style the image, we used the fact that the image is a descendent of the vcard element, and a descendent selector. In my experience, the very widely supported, powerful descendent selector is one of the most underused aspects of CSS. So if you don\u2019t use it frequently, look into it in more detail.\n\nWe added some space to the right of the image, and pulled it up a bit closer to the top of the hCard, like this\n\n\n\nWe also want to add some whitespace between the edge of the hCard and the text. We would typically add padding to the left of the containing element, (in this case the vcard element) but this would break our bottom left hand corner, like this\n\n\n\nThat\u2019s because the div element we added this bottom left background image to would be moved in by the padding on its containing element.\n\nSo instead, we add left margin to all the paragraphs in the hCard\n\n.vcard p {\n\tmargin-left: 1em;\n}\n\n(there is the descendent selector again \u2013 it is the swiss army knife of CSS)\n\nNow, we\u2019ve not yet made the width of the hCard a function of the size of the text inside it (or \u201cem driven\u201d as we described it earlier). We do this by giving the hCard a width that is specified in em units. Here we\u2019ll set a width of say 28em, which makes the hCard always roughly as wide as 28 characters (strictly speaking 28 times the width of the letter capital M). \n\nSo the statement for our containing vcard element becomes\n\n.vcard {\n\tbackground-image: url(images/vcardfill.png);\n\tbackground-repeat: no-repeat;\n\tcolor: #666;\n\tfont-family: \"Lucida Grande\", Verdana, Helvetica, Arial, sans-serif;\n\twidth: 28em;\n}\n\nand now our element will look like this\n\n\n\nWe\u2019ve used almost entirely the existing HTML from our original hCard (adding just a little, and trying as much as possible to keep that additional markup meaningful), and just 6 CSS statements.\n\nHoliday Bonus \u2013 a downloadable vCard\n\nDid you notice this part of the HTML\n\n\n \"download\n\nWhat\u2019s with the odd looking url\n\n\n\t\n\t\tMatch points\n\t\n\t\n\t\n\t\n\t\n\n\nThe span inside each legend is because legend elements are highly resistant to styling! Indeed they\u2019re one of the most stubborn elements in the browsers\u2019 vocabulary. Oh man \u2026 how I wrestled with the buggers \u2026 until this obvious alternative occurred to me! So the legend element itself is just a container, while all the styling is on the inner span.\n\nOh yeah, there was some CSS too\n\nI\u2019m not gonna dwell too much on the CSS it took to make this work \u2013 this is a short article, and it\u2019s all there in the demo [demo page, style sheet]\n\nBut I do want to touch on the most interesting bit \u2013 where we get from a layout with headers on every row, to one where only the top row has headers \u2013 or at least, so it appears to graphical browsers. For screen readers, as we noted, we need those headers on every row, so we should employ some cunning CSS to partly negate their visual presence, without removing them from the output.\n\nThe core styling for each label span is like this:\n\nlabel span\n{\n\tdisplay:block;\n\tpadding:5px;\n\tline-height:1em;\n\tbackground:#423221;\n\tcolor:#fff;\n\tfont-weight:bold;\n}\n\nBut in the rows below the header they have these additional rules:\n\nfieldset.body label span\n{\n\tpadding:0 5px;\n\tline-height:0;\n\tposition:relative;\n\ttop:-10000em;\n}\n\nThe rendered width of the element is preserved, ensuring that the surrounding label is still the same width as the one in the header row above, and hence a unified column width is preserved all the way down. But the element effectively has no height, and so it\u2019s effectively invisible. The styling is done this way, rather than just setting the height to zero and using overflow:hidden, because to do that would expose an unrelated quirk with another popular screen reader! (It would hide the output from Window Eyes, as shown in this test example at access matters.)\n\nThe finished widget\n\nIt\u2019s an intricate beast allright! But after all that we do indeed get the widget we want:\n\n\n\tDemo page\n\tStyle sheet\n\n\nIt\u2019s not perfect, most notably because the legends have to have a fixed width; this can be in em to allow for text scaling, but it still doesn\u2019t allow the content to break into multiple lines. It also doesn\u2019t look quite right in Safari; and some CSS hacking was needed to make it look right in IE6 and IE7.\n\nStill it worked well enough for the purpose, and satisfied the client completely. And most of all it re-assured me in my faith \u2013 that there\u2019s never any need to abuse tables for layout. (Unless of course you think this content is a table anyway, but that\u2019s another story!)", "year": "2006", "author": "James Edwards", "author_slug": "jamesedwards", "published": "2006-12-11T00:00:00+00:00", "url": "https://24ways.org/2006/showing-good-form/", "topic": "ux"} {"rowid": 138, "title": "Rounded Corner Boxes the CSS3 Way", "contents": "If you\u2019ve been doing CSS for a while you\u2019ll know that there are approximately 3,762 ways to create a rounded corner box. The simplest techniques rely on the addition of extra mark-up directly to your page, while the more complicated ones add the mark-up though DOM manipulation. While these techniques are all very interesting, they do seem somewhat of a kludge. The goal of CSS is to separate structure from presentation, yet here we are adding superfluous mark-up to our code in order to create a visual effect. The reason we are doing this is simple. CSS2.1 only allows a single background image per element.\n\nThankfully this looks set to change with the addition of multiple background images into the CSS3 specification. With CSS3 you\u2019ll be able to add not one, not four, but eight background images to a single element. This means you\u2019ll be able to create all kinds of interesting effects without the need of those additional elements.\n\nWhile the CSS working group still seem to be arguing over the exact syntax, Dave Hyatt went ahead and implemented the currently suggested mechanism into Safari. The technique is fiendishly simple, and I think we\u2019ll all be a lot better off once the W3C stop arguing over the details and allow browser vendors to get on and provide the tools we need to build better websites.\n\nTo create a CSS3 rounded corner box, simply start with your box element and apply your 4 corner images, separated by commas.\n\n.box {\n\tbackground-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);\n}\n\nWe don\u2019t want these background images to repeat, which is the normal behaviour, so lets set all their background-repeat properties to no-repeat.\n\n.box {\n\tbackground-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);\n\tbackground-repeat: no-repeat, no-repeat, no-repeat, no-repeat;\n}\n\nLastly, we need to define the positioning of each corner image.\n\n.box {\n\tbackground-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);\n\tbackground-repeat: no-repeat, no-repeat, no-repeat, no-repeat;\n\tbackground-position: top left, top right, bottom left, bottom right;\n}\n\nAnd there we have it, a simple rounded corner box with no additional mark-up.\n\nAs well as using multiple background images, CSS3 also has the ability to create rounded corners without the need of any images at all. You can do this by setting the border-radius property to your desired value as seen in the next example.\n\n.box {\n\tborder-radius: 1.6em;\n}\n\nThis technique currently works in Firefox/Camino and creates a nice, if somewhat jagged rounded corner. If you want to create a box that works in both Mozilla and WebKit based browsers, why not combine both techniques and see what happens.", "year": "2006", "author": "Andy Budd", "author_slug": "andybudd", "published": "2006-12-04T00:00:00+00:00", "url": "https://24ways.org/2006/rounded-corner-boxes-the-css3-way/", "topic": "code"} {"rowid": 142, "title": "Revealing Relationships Can Be Good Form", "contents": "A few days ago, a colleague of mine \u2013 someone I have known for several years, who has been doing web design for several years and harks back from the early days of ZDNet \u2013 was running through a prototype I had put together for some user testing. As with a lot of prototypes, there was an element of \u2018smoke and mirrors\u2019 to make things look like they were working. \n\nOne part of the form included a yes/no radio button, and selecting the Yes option would, in the real and final version of the form, reveal some extra content. Rather than put too much JavaScript in the prototype, I took a preverbial shortcut and created a link which I wrapped around the text next to the radio button \u2013 clicking on that link would cause the form to mimic a change event on the radio button. But it wasn\u2019t working for him. \n\nWhy was that? Because whereas I created the form using a I\u2019d placed around the text). Bah! There goes my time-saver.\n\nSo, what did I learn? That a web professional who has used the Internet for years had neither heard of the
\n\t.net\n\tadvertising\n\tajax\n\t...\n
\n\nUnfortunately, that is one of the worst examples of tag cloud markup I have ever seen. The page states that a tag cloud is a list of tags where size reflects popularity. However, despite describing it in this way to the human readers, the page\u2019s author hasn\u2019t described it that way in the markup. It isn\u2019t a list of tags, just a bunch of anchors in a
. This is also inaccessible because a screenreader will not pause between adjacent links, and in some configurations will not announce the individual links, but rather all of the tags will be read as just one link containing a whole bunch of words. Markup crime number one. \n\nFlickr \n\nAh, Flickr. The darling photo sharing site of the internet, and the biggest blind spot in every standardista\u2019s vision. Forgive it for having atrocious markup and sometimes confusing UI because it\u2019s just so much damn fun to use. Let\u2019s see what they do. \n\n

\n\t\u00a006\u00a0\n\t\u00a0africa\u00a0\n\t\u00a0amsterdam\u00a0\n\t...\n

\n\nAgain we have a simple collection of anchors like del.icio.us, only this time in a paragraph. But rather than using a class to represent the size of the tag they use an inline style. An inline style using a pixel-based font size. That\u2019s so far away from the goal of separating style from content, they might as well use a tag. You could theoretically parse that to extract the information, but you have more work to guess what the pixel sizes represent. Markup crime number two (and extra jail time for using non-breaking spaces purely for visual spacing purposes.)\n\nTechnorati \n\nAh, now. Here, you\u2019d expect something decent. After all, the Overlord of microformats and King of Semantics Tantek \u00c7elik works there. Surely we\u2019ll see something decent here? \n\n
    \n\t
  1. Britney Spears
  2. \n\t
  3. Bush
  4. \n\t
  5. Christmas
  6. \n\t...\n\t
  7. SEO
  8. \n\t
  9. Shopping
  10. \n\t...\n
\n\nUnfortunately it turns out not to be that decent, and stop calling me Shirley. It\u2019s not exactly terrible code. It does recognise that a tag cloud is a list of links. And, since they\u2019re in alphabetical order, that it\u2019s an ordered list of links. That\u2019s nice. However \u2026 fifteen nested tags? FIFTEEN? That\u2019s emphasis for you. Yes, it is parse-able, but it\u2019s also something of a strange way of looking at emphasis. The HTML spec states that is emphasis, and is for stronger emphasis. Nesting tags seems counter to the idea that different tags are used for different levels of emphasis. Plus, if you had a screen reader that stressed the voice for emphasis, what would it do? Shout at you? Markup crime number three. \n\nSo what should it be? \n\nAs del.icio.us tells us, a tag cloud is a list of tags where the size that they are rendered at contains extra information. However, by hiding the extra context purely within the CSS or the HTML tags used, you are denying that context to some users. The basic assumption being made is that all users will be able to see the difference between font sizes, and this is demonstrably false. \n\nA better way to code a tag cloud is to put the context of the cloud within the content, not the markup or CSS alone. As an example, I\u2019m going to take some of my favourite flickr tags and put them into a cloud which communicates the relative frequency of each tag. \n\nTo start with a tag cloud in its most basic form is just a list of links. I am going to present them in alphabetical order, so I\u2019ll use an ordered list. Into each list item I add the number of photos I have with that particular tag. The tag itself is linked to the page on flickr which contains those photos. So we end up with this first example. To display this as a traditional tag cloud, we need to alter it in a few ways: \n\n\n\tThe items need to be displayed next to each other, rather than one-per-line\n\tThe context information should be hidden from display (but not from screen readers)\n\tThe tag should link to the page of items with that tag\n\n\nDisplaying the items next to each other simply means setting the display of the list elements to inline. The context can be hidden by wrapping it in a and then using the off-left method to hide it. And the link just means adding an anchor (with rel=\"tag\" for some extra microformats bonus points). So, now we have a simple collection of links in our second example. \n\nThe last stage is to add the sizes. Since we already have context in our content, the size is purely for visual rendering, so we can just use classes to define the different sizes. For my example, I\u2019ll use a range of class names from not-popular through ultra-popular, in order of smallest to largest, and then use CSS to define different font sizes. If you preferred, you could always use less verbose class names such as size1 through size6. Anyway, adding some classes and CSS gives us our final example, a semantic and more accessible tag cloud.", "year": "2006", "author": "Mark Norman Francis", "author_slug": "marknormanfrancis", "published": "2006-12-09T00:00:00+00:00", "url": "https://24ways.org/2006/marking-up-a-tag-cloud/", "topic": "code"} {"rowid": 129, "title": "Knockout Type - Thin Is Always In", "contents": "OS X has gorgeous native anti-aliasing (although I will admit to missing 10px aliased Geneva \u2014 *sigh*). This is especially true for dark text on a light background. However, things can go awry when you start using light text on a dark background. Strokes thicken. Counters constrict. Letterforms fill out like seasonal snackers.\n\n \n\nSo how do we combat the fat? In Safari and other Webkit-based browsers we can use the CSS \u2018text-shadow\u2019 property. While trying to add a touch more contrast to the navigation on haveamint.com I noticed an interesting side-effect on the weight of the type. \n\n\n\nThe second line in the example image above has the following style applied to it:\n\n \n\nThis creates an invisible drop-shadow. (Why is it invisible? The shadow is positioned directly behind the type (the first two zeros) and has no spread (the third zero). So the color, black, is completely eclipsed by the type it is supposed to be shadowing.)\n\n \n\nWhy applying an invisible drop-shadow effectively lightens the weight of the type is unclear. What is clear is that our light-on-dark text is now of a comparable weight to its dark-on-light counterpart.\n\n \n\nYou can see this trick in effect all over ShaunInman.com and in the navigation on haveamint.com and Subtraction.com. The HTML and CSS source code used to create the example images used in this article can be found here.", "year": "2006", "author": "Shaun Inman", "author_slug": "shauninman", "published": "2006-12-17T00:00:00+00:00", "url": "https://24ways.org/2006/knockout-type/", "topic": "code"} {"rowid": 126, "title": "Intricate Fluid Layouts in Three Easy Steps", "contents": "The Year of the Script may have drawn attention away from CSS but building fluid, multi-column, cross-browser CSS layouts can still be as unpleasant as a lump of coal. Read on for a worry-free approach in three quick steps.\n\nThe layout system I developed, YUI Grids CSS, has three components. They can be used together as we\u2019ll see, or independently.\n\nThe Three Easy Steps\n\n\n\tChoose fluid or fixed layout, and choose the width (in percents or pixels) of the page.\n\tChoose the size, orientation, and source-order of the main and secondary blocks of content.\n\tChoose the number of columns and how they distribute (for example 50%-50% or 25%-75%), using stackable and nestable grid structures.\n\n\nThe Setup\n\nThere are two prerequisites: We need to normalize the size of an em and opt into the browser rendering engine\u2019s Strict Mode.\n\nEms are a superior unit of measure for our case because they represent the current font size and grow as the user increases their font size setting. This flexibility\u2014the container growing with the user\u2019s wishes\u2014means larger text doesn\u2019t get crammed into an unresponsive container. We\u2019ll use YUI Fonts CSS to set the base size because it provides consistent-yet-adaptive font-sizes while preserving user control.\n\nThe second prerequisite is to opt into Strict Mode (more info on rendering modes) by declaring a Doctype complete with URI. You can choose XHTML or HTML, and Transitional or Strict. I prefer HTML 4.01 Strict, which looks like this:\n\n\n\nIncluding the CSS\n\nA single small CSS file powers a nearly-infinite number of layouts thanks to a recursive system and the interplay between the three distinct components. You could prune to a particular layout\u2019s specific needs, but why bother when the complete file weighs scarcely 1.8kb uncompressed? Compressed, YUI Fonts and YUI Grids combine for a miniscule 0.9kb over the wire.\n\nYou could save an HTTP request by concatenating the two CSS files, or by adding their contents to your own CSS, but I\u2019ll keep them separate for now:\n\n\n\n\nExample: The Setup\n\nNow we\u2019re ready to build some layouts.\n\nStep 1: Choose Fluid or Fixed Layout\n\nChoose between preset widths of 750px, 950px, and 100% by giving a document-wrapping div an ID of doc, doc2, or doc3. These options cover most use cases, but it\u2019s easy to define a custom fixed width.\n\nThe fluid 100% grid (doc3) is what I\u2019ve been using almost exclusively since it was introduced in the last YUI released.\n\n\n\t
\n\n\nAll pages are centered within the viewport, and grow with font size. The 100% width page (doc3) preserves 10px of breathing room via left and right margins. If you prefer your content flush to the viewport, just add doc3 {margin:auto} to your CSS.\n\nRegardless of what you choose in the other two steps, you can always toggle between these widths and behaviors by simply swapping the ID value. It\u2019s really that simple.\n\nExample: 100% fluid layout\n\nStep 2: Choose a Template Preset\n\nThis is perhaps the most frequently omitted step (they\u2019re all optional), but I use it nearly every time. In a source-order-independent way (good for accessibility and SEO), \u201cTemplate Presets\u201d provide commonly used template widths compatible with ad-unit dimension standards defined by the Interactive Advertising Bureau, an industry association.\n\nChoose between the six Template Presets (.yui-t1 through .yui-t6) by setting the class value on the document-wrapping div established in Step 1. Most frequently I use yui-t3, which puts the narrow secondary block on the left and makes it 300px wide. \n\n\n\t
\n\n\nThe Template Presets control two \u201cblocks\u201d of content, which are defined by two divs, each with yui-b (\u201cb\u201d for \u201cblock\u201d) class values. Template Presets describe the width and orientation of the secondary block; the main block will take up the rest of the space.\n\n\n\t
\n\t
\n\t
\n\t
\n\n\nUse a wrapping div with an ID of yui-main to structurally indicate which block is the main block. This wrapper\u2014not the source order\u2014identifies the main block.\n\n\n\t
\n\t
\n\t
\n\t
\n\t
\n\t
\n\n\nExample: Main and secondary blocks sized and oriented with .yui-t3 Template Preset\n\nAgain, regardless of what values you choose in the other steps, you can always toggle between these Template Presets by toggling the class value of your document-wrapping div. It\u2019s really that simple.\n\nStep 3: Nest and Stack Grid Structures.\n\nThe bulk of the power of the system is in this third step. The key is that columns are built by parents telling children how to behave. By default, two children each consume half of their parent\u2019s area. Put two units inside a grid structure, and they will sit side-by-side, and they will each take up half the space. Nest this structure and two columns become four. Stack them for rows of columns.\n\nAn Even Number of Columns\n\nThe default behavior creates two evenly-distributed columns. It\u2019s easy. Define one parent grid with .yui-g (\u201cg\u201d for grid) and two child units with .yui-u (\u201cu\u201d for unit). The code looks like this:\n\n
\n\t
\n\t
\n
\n\nBe sure to indicate the \u201cfirst\u201c unit because the :first-child pseudo-class selector isn\u2019t supported across all A-grade browsers. It\u2019s unfortunate we need to add this, but luckily it\u2019s not out of place in the markup layer since it is structural information.\n\nExample: Two evenly-distributed columns in the main content block\n\nAn Odd Number of Columns\n\nThe default system does not work for an odd number of columns without using the included \u201cSpecial Grids\u201d classes. To create three evenly distributed columns, use the \u201cyui-gb\u201c Special Grid:\n\n
\n\t
\n\t
\n\t
\n
\n\nExample: Three evenly distributed columns in the main content block\n\nUneven Column Distribution\n\nSpecial Grids are also used for unevenly distributed column widths. For example, .yui-ge tells the first unit (column) to take up 75% of the parent\u2019s space and the other unit to take just 25%.\n\n
\n\t
\n\t
\n
\n\nExample: Two columns in the main content block split 75%-25%\n\nPutting It All Together\n\nStart with a full-width fluid page (div#doc3). Make the secondary block 180px wide on the right (div.yui-t4). Create three rows of columns: Three evenly distributed columns in the first row (div.yui-gb), two uneven columns (66%-33%) in the second row (div.yui-gc), and two evenly distributed columns in the thrid row.\n\n\n\t\n\t
\n\t\t\n\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t\t\n\t\t
\n\t
\n\n\nExample: A complex layout.\n\nWasn\u2019t that easy? Now that you know the three \u201clevers\u201d of YUI Grids CSS, you\u2019ll be creating headache-free fluid layouts faster than you can say \u201cPeace on Earth\u201d.", "year": "2006", "author": "Nate Koechley", "author_slug": "natekoechley", "published": "2006-12-20T00:00:00+00:00", "url": "https://24ways.org/2006/intricate-fluid-layouts/", "topic": "code"} {"rowid": 121, "title": "Hide And Seek in The Head", "contents": "If you want your JavaScript-enhanced pages to remain accessible and understandable to scripted and noscript users alike, you have to think before you code. Which functionalities are required (ie. should work without JavaScript)? Which ones are merely nice-to-have (ie. can be scripted)? You should only start creating the site when you\u2019ve taken these decisions.\n\nSpecial HTML elements\n\nOnce you have a clear idea of what will work with and without JavaScript, you\u2019ll likely find that you need a few HTML elements for the noscript version only.\n\nTake this example: A form has a nifty bit of Ajax that automatically and silently sends a request once the user enters something in a form field. However, in order to preserve accessibility, the user should also be able to submit the form normally. So the form should have a submit button in noscript browsers, but not when the browser supports sufficient JavaScript.\n\nSince the button is meant for noscript browsers, it must be hard-coded in the HTML:\n\n\n\nWhen JavaScript is supported, it should be removed:\n\nvar checkJS = [check JavaScript support];\nwindow.onload = function () {\n\tif (!checkJS) return;\n\tdocument.getElementById('noScriptButton').style.display = 'none';\n}\n\nProblem: the load event\n\nAlthough this will likely work fine in your testing environment, it\u2019s not completely correct. What if a user with a modern, JavaScript-capable browser visits your page, but has to wait for a huge graphic to load? The load event fires only after all assets, including images, have been loaded. So this user will first see a submit button, but then all of a sudden it\u2019s removed. That\u2019s potentially confusing.\n\nFortunately there\u2019s a simple solution: play a bit of hide and seek in the :\n\nvar checkJS = [check JavaScript support];\nif (checkJS) {\n\tdocument.write('');\n}\n\nFirst, check if the browser supports enough JavaScript. If it does, document.write an extra \n\nSo we end up with a nice simple to understand but also quick to write XSL which can be used on ATOM Flickr feeds and ATOM News feeds. With a little playing around with XSL, you can make XML beautiful again.\n\nAll the files can be found in the zip file (14k)", "year": "2006", "author": "Ian Forrester", "author_slug": "ianforrester", "published": "2006-12-07T00:00:00+00:00", "url": "https://24ways.org/2006/beautiful-xml-with-xsl/", "topic": "code"} {"rowid": 125, "title": "Accessible Dynamic Links", "contents": "Although hyperlinks are the soul of the World Wide Web, it\u2019s worth using them in moderation. Too many links becomes a barrier for visitors navigating their way through a page. This difficulty is multiplied when the visitor is using assistive technology, or is using a keyboard; being able to skip over a block of links doesn\u2019t make the task of finding a specific link any easier.\n\nIn an effort to make sites easier to use, various user interfaces based on the hiding and showing of links have been crafted. From drop-down menus to expose the deeper structure of a website, to a decluttering of skip links so as not to impact design considerations. Both are well intentioned with the aim of preserving a good usability experience for the majority of a website\u2019s audience; hiding the real complexity of a page until the visitor interacts with the element.\n\nWhen JavaScript is not available\n\nThe modern dynamic link techniques rely on JavaScript and CSS, but regardless of whether scripting and styles are enabled or not, we should consider the accessibility implications, particularly for screen-reader users, and people who rely on keyboard access.\n\nIn typical web standards-based drop-down navigation implementations, the rough consensus is that the navigation should be structured as nested lists so when JavaScript is not available the entire navigation map is available to the visitor. This creates a situation where a visitor is faced with potentially well over 50 links on every page of the website. Keyboard access to such structures is frustrating, there\u2019s far too many options, and the method of serially tabbing through each link looking for a specific one is tedious.\n\nInstead of offering the visitor an indigestible chunk of links when JavaScript is not available, consider instead having the minimum number of links on a page, and when JavaScript is available bringing in the extra links dynamically. Santa Chris Heilmann offers an excellent proof of concept in making Ajax navigation optional.\n\nWhen JavaScript is enabled, we need to decide how to hide links. One technique offers a means of comprehensively hiding links from keyboard users and assistive technology users. Another technique allows keyboard and screen-reader users to access links while they are hidden, and making them visible when reached.\n\nHiding the links\n\nIn JavaScript enhanced pages whether a link displays on screen depends on a certain event happening first. For example, a visitor needs to click a top-level navigation link that makes a set of sub-navigation links appear. In these cases, we need to ensure that these links are not available to any user until that event has happened.\n\nThe typical way of hiding links is to style the anchor elements, or its parent nodes with display: none. This has the advantage of taking the links out of the tab order, so they are not focusable. It\u2019s useful in reducing the number of links presented to a screen-reader or keyboard user to a minimum. Although the links are still in the document (they can be referenced and manipulated using DOM Scripting), they are not directly triggerable by a visitor.\n\nOnce the necessary event has happened, like our visitor has clicked on a top-level navigation link which shows our hidden set of links, then we can display the links to the visitor and make them triggerable. This is done simply by undoing the display: none, perhaps by setting the display back to block for block level elements, or inline for inline elements. For as long as this display style remains, the links are in the tab order, focusable by keyboard, and triggerable.\n\nA common mistake in this situation is to use visibility: hidden, text-indent: -999em, or position: absolute with left: -999em to position these links off-screen. But all of these links remain accessible via keyboard tabbing even though the links remain hidden from screen view. In some ways this is a good idea, but for hiding sub-navigation links, it presents the screen-reader user and keyboard user with too many links to be of practical use.\n\nMoving the links out of sight\n\nIf you want a set of text links accessible to screen-readers and keyboard users, but don\u2019t want them cluttering up space on the screen, then style the links with position: absolute; left: -999em. Links styled this way remain in the tab order, and are accessible via keyboard. (The position: absolute is added as a style to the link, not to a parent node of the link \u2013 this will give us a useful hook to solve the next problem).\n\na.helper {\n\tposition: absolute;\n\tleft: -999em;\n}\n\nOne important requirement when displaying links off-screen is that they are visible to a keyboard user when they receive focus. Tabbing on a link that is not visible is a usability mudpit, since the visitor has no visible cue as to what a focused link will do, or where it will go.\n\nThe simple answer is to restyle the link so that it appears on the screen when the hidden link receives focus. The anchor\u2019s :focus pseudo-class is a logical hook to use, and with the following style repositions the link onscreen when it receives the focus:\n\na.helper:focus, a.helper.focus {\n\ttop: 0;\n\tleft: 0;\n}\n\nThis technique is useful for hiding skip links, and options you want screen-reader and keyboard users to use, but don\u2019t want cluttering up the page. Unfortunately Internet Explorer 6 and 7 don\u2019t support the focus pseudo-class, which is why there\u2019s a second CSS selector a.helper.focus so we can use some JavaScript to help out. When the page loads, we look for all links that have a class of helper and add in onfocus and onblur event handlers:\n\nif (anchor.className == \"helper\") {\n\tanchor.onfocus = function() {\n\t\tthis.className = 'helper focus';\n\t}\n\tanchor.onblur = function() {\n\t\tthis.className = 'helper';\n\t}\n}\n\nSince we are using JavaScript to cover up for deficiencies in Internet Explorer, it makes sense to use JavaScript initially to place the links off-screen. That way an Internet Explorer user with JavaScript disabled can still use the skip link functionality.\n\nIt is vital that the number of links rendered in this way is kept to a minimum. Every link you offer needs to be tabbed through, and gets read out in a screen reader. Offer these off-screen links that directly benefit these types of visitor.\n\nAndy Clarke and Kimberly Blessing use a similar technique in the Web Standards Project\u2018s latest design, but their technique involves hiding the skip link in plain sight and making it visible when it receives focus. Navigate the page using just the tab key to see the accessibility-related links appear when they receive focus.\n\nThis technique is also a good way of hiding image replaced text. That way the screen-readers still get the actual text, and the website still gets its designed look.\n\nWhich way?\n\nIf the links are not meant to be reachable until a certain event has occurred, then the display: none technique is the preferred approach. If you want the links accessible but out of the way until they receive focus, then the off-screen positioning (or Andy\u2019s hiding in plain sight technique) is the way to go.", "year": "2006", "author": "Mike Davies", "author_slug": "mikedavies", "published": "2006-12-05T00:00:00+00:00", "url": "https://24ways.org/2006/accessible-dynamic-links/", "topic": "ux"} {"rowid": 135, "title": "A Scripting Carol", "contents": "We all know the stories of the Ghost of Scripting Past \u2013 a time when the web was young and littered with nefarious scripting, designed to bestow ultimate control upon the developer, to pollute markup with event handler after event handler, and to entrench advertising in the minds of all that gazed upon her.\n\nAnd so it came to be that JavaScript became a dirty word, thrown out of solutions by many a Scrooge without regard to the enhancements that JavaScript could bring to any web page. JavaScript, as it was, was dead as a door-nail.\n\nWith the arrival of our core philosophy that all standardistas hold to be true: \u201cseparate your concerns \u2013 content, presentation and behaviour,\u201d we are in a new era of responsible development the Web Standards Way\u2122. Or are we? Have we learned from the Ghosts of Scripting Past? Or are we now faced with new problems that come with new ways of implementing our solutions?\n\nThe Ghost of Scripting Past\n\nIf the Ghost of Scripting Past were with us it would probably say: \n\n\n\tYou must remember your roots and where you came from, and realize the misguided nature of your early attempts for control. That person you see down there, is real and they are the reason you exist in the first place\u2026 without them, you are nothing.\n\n\nIn many ways we\u2019ve moved beyond the era of control and we do take into account the user, or at least much more so than we used to. Sadly \u2013 there is one advantage that old school inline event handlers had where we assigned and reassigned CSS style property values on the fly \u2013 we knew that if JavaScript wasn\u2019t supported, the styles wouldn\u2019t be added because we ended up doing them at the same time.\n\nIf anything, we need to have learned from the past that just because it works for us doesn\u2019t mean it is going to work for anyone else \u2013 we need to test more scenarios than ever to observe the multitude of browsing arrangements we\u2019ll observe: CSS on with JavaScript off, CSS off/overridden with JavaScript on, both on, both off/not supported. It is a situation that is ripe for conflict.\n\nThis may shock some of you, but there was a time when testing was actually easier: back in the day when Netscape 4 was king. Yes, that\u2019s right. I actually kind of enjoyed Netscape 4 (hear me out, please). With NS4\u2019s CSS implementation known as JavaScript Style Sheets, you knew that if JavaScript was off the styles were off too.\n\nThe Ghost of Scripting Present\n\nWith current best practice \u2013 we keep our CSS and JavaScript separate from each other. So what happens when some of our fancy, unobtrusive DOM Scripting doesn\u2019t play nicely with our wonderfully defined style rules?\n\nLets look at one example of a collapsing and expanding menu to illustrate where we are now:\n\nSimple Collapsing/Expanding Menu Example\n\nWe\u2019re using some simple JavaScript (I\u2019m using jquery in this case) to toggle between a CSS state for expanded and not expanded:\n\nJavaScript\n\n$(document).ready(function(){\n\tTWOFOURWAYS.enableTree();\n});\nvar TWOFOURWAYS = new Object();\nTWOFOURWAYS.enableTree = function ()\n{\n\t$(\"ul li a\").toggle(function(){\n\t\t$(this.parentNode).addClass(\"expanded\");\n\t}, function() {\n\t\t$(this.parentNode).removeClass(\"expanded\");\n\t});\n\treturn false;\t\n}\n\nCSS\n\nul li ul {\n\tdisplay: none;\n}\nul li.expanded ul {\n\tdisplay: block;\n}\n\nAt this point we\u2019ve separated our presentation from our content and behaviour, and all is well, right?\n\nNot quite.\n\nHere\u2019s where I typically see failures in the assessment work that I do on web sites and applications (Yes, call me Scrooge \u2013 I don\u2019t care!). We know our page needs to work with or without scripting, and we know it needs to work with or without CSS. All too often the testing scenarios don\u2019t take into account combinations.\n\nTesting it out\n\nSo what happens when we test this? Make sure you test with:\n\n\n\tCSS off\n\tJavaScript off\n\n\nUse the simple example again.\n\nWith CSS off, we revert to a simple nested list of links and all functionality is maintained. With JavaScript off, however, we run into a problem \u2013 we have now removed the ability to expand the menu using the JavaScript triggered CSS change.\n\nHopefully you see the problem \u2013 we have a JavaScript and CSS dependency that is critical to the functionality of the page. Unobtrusive scripting and binary on/off tests aren\u2019t enough. We need more.\n\nThis Ghost of Scripting Present sighting is seen all too often.\n\nLets examine the JavaScript off scenario a bit further \u2013 if we require JavaScript to expand/show the branch of the tree we should use JavaScript to hide them in the first place. That way we guarantee functionality in all scenarios, and have achieved our baseline level of interoperability. \n\nTo revise this then, we\u2019ll start with the sub items expanded, use JavaScript to collapse them, and then use the same JavaScript to expand them.\n\nHTML\n\n\n\nCSS\n\n/* initial style is expanded */\nul li ul.collapseme {\n\tdisplay: block;\n}\n\nJavaScript\n\n// remove the class collapseme after the page loads\n$(\"ul ul.collapseme\").removeClass(\"collapseme\");\n\nAnd there you have it \u2013 a revised example with better interoperability.\n\nThis isn\u2019t rocket surgery by any means. It is a simple solution to a ghostly problem that is too easily overlooked (and often is).\n\nThe Ghost of Scripting Future\n\nWell, I\u2019m not so sure about this one, but I\u2019m guessing that in a few years\u2019 time, we\u2019ll all have seen a few more apparitions and have a few more tales to tell. And hopefully we\u2019ll be able to share them on 24 ways.\n\nThanks to Drew for the invitation to contribute and thanks to everyone else out there for making this a great (and haunting) year on the web!", "year": "2006", "author": "Derek Featherstone", "author_slug": "derekfeatherstone", "published": "2006-12-21T00:00:00+00:00", "url": "https://24ways.org/2006/a-scripting-carol/", "topic": "code"}