{"rowid": 192, "title": "Cleaner Code with CSS3 Selectors", "contents": "The parts of CSS3 that seem to grab the most column inches on blogs and in articles are the shiny bits. Rounded corners, text shadow and new ways to achieve CSS layouts are all exciting and bring with them all kinds of possibilities for web design. However what really gets me, as a developer, excited is a bit more mundane. \n\nIn this article I\u2019m going to take a look at some of the ways our front and back-end code will be simplified by CSS3, by looking at the ways we achieve certain visual effects now in comparison to how we will achieve them in a glorious, CSS3-supported future. I\u2019m also going to demonstrate how we can use these selectors now with a little help from JavaScript \u2013 which can work out very useful if you find yourself in a situation where you can\u2019t change markup that is being output by some server-side code.\n\nThe wonder of nth-child\n\nSo why does nth-child get me so excited? Here is a really common situation, the designer would like the tables in the application to look like this:\n\n\n\nSetting every other table row to a different colour is a common way to enhance readability of long rows. The tried and tested way to implement this is by adding a class to every other row. If you are writing the markup for your table by hand this is a bit of a nuisance, and if you stick a row in the middle you have to change the rows the class is applied to. If your markup is generated by your content management system then you need to get the server-side code to add that class \u2013 if you have access to that code.\n\n\n\n
\nName | \n\t\t\tCards sent | \n\t\t\tCards received | \n\t\t\tCards written but not sent | \n\t\t
---|---|---|---|
Ann | \n\t\t\t40 | \n\t\t\t28 | \n\t\t\t4 | \n\t\t
Joe | \n\t\t\t2 | \n\t\t\t27 | \n\t\t\t29 | \n\t\t
Paul | \n\t\t\t5 | \n\t\t\t35 | \n\t\t\t2 | \n\t\t
Louise | \n\t\t\t65 | \n\t\t\t65 | \n\t\t\t0 | \n\t\t
Please wait while we do what we do best.
\n\nLooks semantic enough to me! Here\u2019s the basic HTML I\u2019m using to position the element in the center of the screen, and make the text inside it disappear:\n\n#spinner {\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\tmargin: -100px 0 0 -100px;\n\theight: 200px;\n\twidth: 200px;\n\ttext-indent: 250px;\n\twhite-space: nowrap;\n\toverflow: hidden;\n}\n\nCool, but now we don\u2019t see anything. Let\u2019s pull rabbit number one out of the hat: -webkit-mask-image (accompanied by the previously mentioned transparent PNG image):\n\n#spinner {\n\t...\n\t-webkit-mask-image: url(../img/spinner.png);\n}\n\nBy now you should be feeling like a magician already. Oh, wait, we still have a blank screen, looks like we left something in the hat (tip: not rabbit droppings):\n\n#spinner {\n\t...\n\t-webkit-mask-image: url(../img/spinner.png);\n\tbackground-color: #000;\n}\n\nNice! What we\u2019ve done right here is telling the element to clip onto the PNG. It\u2019s a lot like clipping layers in Photoshop. So, spinners, they move, right? Into the hat again, and look what we pull out this time: CSS animations!\n\n#spinner {\n\t...\n\t-webkit-mask-image: url(../img/spinner.png);\n\tbackground-color: #000;\n\t-webkit-animation-name: spinnerRotate;\n\t-webkit-animation-duration: 2s;\n\t-webkit-animation-iteration-count: infinite;\n\t-webkit-animation-timing-function: linear;\n}\n\nSome explanation:\n\n\n\t-webkit-animation-name: Name of the animation we\u2019ll be defining later.\n\t-webkit-animation-duration: The timespan of the animation.\n\t-webkit-animation-iteration-count: Repeat once, a defined number of times or infinitely?\n\t-webkit-animation-timing-function: Linear is the one you\u2019ll be using mostly. Other options are ease-in, ease-out, ease-in-out\u2026\n\n\nLet\u2019s define spinnerRotate:\n\n@-webkit-keyframes spinnerRotate {\n\tfrom {\n\t\t-webkit-transform:rotate(0deg);\n\t}\n\tto {\n\t\t-webkit-transform:rotate(360deg);\n\t}\n}\n\nEn Anglais: Rotate #spinner starting at 0 degrees, ending at 360 degrees, over a timespan of 2 seconds, at a constant speed, and keep repeating this animation forever.\n\nThat\u2019s it! See it in action on the demo page.\n\nNote: these examples only work when you\u2019re using a WebKit-based browser like Safari, Mobile Safari or Google Chrome. I\u2019m confident though that Mozilla and Opera will try their very best catching up with all this new CSS goodness soon.\n\nWhen looking at this example, you see the possibilities are endless. Another advantage is you can change the look of it entirely by only changing a couple of lines of CSS, instead of re-creating and re-downloading the image from some website smelling like web 2.0 gone bad. I made another demo that shows how great it is to be able to change background and foreground colors (even on the fly!).\n\nSo there you have it, a smoothly animated, fully transparent and completely customizable spinner. Cool? I think so. (Ladies?)\n\nBut you can do a lot more with CSS animations than just create pretty spinners. Since I was fooling around with it anyway, I decided to test how far you can push this, space is the final limit, right?\n\nConclusion\n\nCSS has never been more exciting than it is right now. I\u2019m even prepared to say CSS is \u201ccool\u201d again, both for the more experienced front-end developers as for the new designers discovering CSS every day now.\n\nBut\u2026\n\nRemember when Javascript became popular? Remember when Flash became popular? Every time we\u2019re been given new toys, some people aren\u2019t ashamed to use it in a way you can barely call constructive. I\u2019m thinking of Geocities websites, loaded with glowing blocks of text, moving images, bad color usage\u2026 In the wise words of Stan Lee: With great power there must also come great responsibility! A sprinkle of CSS animations is better than a bucket load. Apply with care.", "year": "2009", "author": "Tim Van Damme", "author_slug": "timvandamme", "published": "2009-12-15T00:00:00+00:00", "url": "https://24ways.org/2009/css-animations/", "topic": "code"} {"rowid": 190, "title": "Self-Testing Pages with JavaScript", "contents": "Working at an agency I am involved more and more on projects in which client side code is developed internally then sent out to a separate team for implementation. You provide static HTML, CSS and JavaScript which then get placed into the CMS and brought to life as an actual website. As you can imagine this can sometimes lead to frustrations. However many safeguards you include, handing over your code to someone else is always a difficult thing to do effectively.\n\nIn this article I will show you how you can create a JavaScript implementation checker and that will give you more time for drink based activity as your web site and apps are launched quicker and with less unwanted drama!\n\nAn all too frequent occurrence\n\nYou\u2019ve been working on a project for weeks, fixed all your bugs and send it to be implemented. You hear nothing and assume all is going well then a few days before it\u2019s meant to launch you get an email from the implementation team informing you of bugs in your code that you need to urgently fix.\n\n The 24ways website with a misspelt ID for the years menu\n\nBeing paranoid you trawl through the preview URL, check they have the latest files, check your code for errors then notice that a required HTML attribute has been omitted from the build and therefore CSS or JavaScript you\u2019ve hooked onto that particular attribute isn\u2019t being applied and that\u2019s what is causing the \u201cbug\u201d.\n\nIt takes you seconds drafting an email informing them of this, it takes then seconds putting the required attribute in and low and behold the bug is fixed, everyone is happy but you\u2019ve lost a good few hours of your life \u2013 this time could have been better spent in the pub.\n\nI\u2019m going to show you a way that these kind of errors can be alerted immediately during implementation of your code and ensure that when you are contacted you know that there actually is a bug to fix. You probably already know the things that could be omitted from a build and look like bugs so you\u2019ll soon be creating tests to look for these and alert when they are not found on the rendered page. The error is reported directly to those who need to know about it and fix it. Less errant bug reports and less frantic emails ahoy!\n\n A page with an implementation issue and instant feedback on the problem\n\nJavaScript selector engines to the rescue\n\nWhether you\u2019re using a library or indeed tapping into the loveliness of the new JavaScript Selector APIs looking for particular HTML elements in JavaScript is fairly trivial now. \n\nFor instance this is how you look for a div element with the id attribute of year (the missing attribute from top image) using jQuery (the library I\u2019ll be coding my examples in): \n\nif ($(\u2018div#year\u2019).length) {\n\talert(\u2018win\u2019);\n}\n\nUsing this logic you can probably imagine how you can write up a quick method to check for the existence of a particular element and alert when it\u2019s not present \u2014 but assuming you have a complex page you\u2019re going to be repeating yourself a fair bit and we don\u2019t want to be doing that.\n\nTest scripts\n\nIf you\u2019ve got a lot of complex HTML patterns that need testing across a number of different pages it makes sense to keep your tests out of production code. Chances are you\u2019ve already got a load of heavy JavaScript assets, and when it comes to file size saving every little helps.\n\nI don\u2019t think that tests should contain code inside of them so keep mine externally as JSON. This also means that you can use the one set of tests in multiple places. We already know that it\u2019s a good idea to keep our CSS and JavaScript separate so lets continue along those lines here.\n\nThe test script for this example looks like this:\n\n{\n\t\"title\": \"JS tabs implementation test\",\n\t\"description\": \"Check that the correct HTML patterns has been used\",\n\t\"author\": \"Ross Bruniges\",\n\t\"created\": \"20th July 2009\",\n\t\"tests\": [\n\t\t{\n\t\t\t\"name\": \"JS tabs elements\",\n\t\t\t\"description\": \"Checking that correct HTML elements including class/IDs are used on the page for the JS to progressively enhance\",\n\t\t\t\"selector\": \"div.tabbed_content\",\n\t\t\t\"message\": \"We couldn't find VAR on the page - it's required for our JavaScript to function correctly\",\n\t\t\t\"check_for\": {\n\t\t\t\t\"contains\": {\n\t\t\t\t\t\"elements\": [\n\t\t\t\t\t\t\"div.tab_content\", \"h2\" \n\t\t\t\t\t],\n\t\t\t\t\t\"message\": \"We've noticed some missing HTML:please refer to the examples sent for reference\" \n\t\t\t\t} \n\t\t\t} \n\t\t} \n\t]\n}\n\nThe first four lines are just a little bit of meta data so we remember what this test was all about when we look at it again in the future, or indeed if it ever breaks. The tests are the really cool parts and firstly you\u2019ll notice that it\u2019s an array \u2013 we\u2019re only going to show one example test here but there is no reason why you can\u2019t place in as many as you want. I\u2019ll explain what each of the lines in the example test means:\n\n\n\tname \u2013 short test name, I use this in pass/fail messaging later\n\tdescription \u2013 meta data for future reference\n\tselector \u2013 the root HTML element from which your HTML will be searched\n\tmessage \u2013 what the app will alert if the initial selector isn\u2019t found\n\tcheck_for \u2013 a wrapper to hold inner tests \u2013 those run if the initial selector does match\n\t\n\t\tcontains \u2013 the type of check, we\u2019re checking that the selector contains specified elements\n\t\t\n\t\t\telements \u2013 the HTML elements we are searching for\n\t\t\tmessage \u2013 a message for when these don\u2019t match (VAR is substituted when it\u2019s appended to the page with the name of any elements that don\u2019t exist)\n\t\t\n\t\t\n\t\t\n\nIt\u2019s very important to pass the function valid JSON (JSONLint is a great tool for this) otherwise you might get a console showing no tests have even been run. \n\nThe JavaScript that makes this helpful\n\nAgain, this code should never hit a production server so I\u2019ve kept it external. This also means that the only thing that\u2019s needed to be done by the implementation team when they are ready to build is that they delete this code.\n\n\n\n\n\u201cView the full JavaScript:/examples/self-testing-pages-with-javascript/js/tests/test_suite.js\n\nThe init function appends the test console to the page and inserts the CSS file required to style it (you don\u2019t need to use pictures of me when tests pass and fail though I see no reason why you shouldn\u2019t), goes and grabs the JSON file referenced and parses it. The methods to pass (tests_pass) and fail (haz_fail) the test I hope are pretty self-explanatory as is the one which creates the test summary once everything has been run (create_summary).\n\nThe two interesting functions are init_tests and confirm_html.\n\ninit_tests\n\ninit_tests:function(i,obj) {\n\tvar $master_elm = $(obj.selector);\n\tsleuth.test_page.$logger.append(\"
\");\n\tvar $container = $('#test_' + i);\n\tif (!$master_elm.length) {\n\t\tvar err_sum = obj.message.replace(/VAR/gi, obj.selector);\n\t\tsleuth.test_page.haz_failed(err_sum, $container);\n\t\treturn;\n\t}\n\tif (obj.check_for) {\n\t\t$.each(obj.check_for,function(key, value){\n\t\t\tsleuth.test_page.assign_checks($master_elm, $container, key, value);\n\t\t});\n\t} else {\n\t\tsleuth.test_page.tests_passed($container);\n\t\treturn;\n\t}\n}\n\nThe function gets sent the number of the current iteration (used to create a unique id for its test summary) and the current object that contains the data we\u2019re testing against as parameters.\n\nWe grab a reference to the root element and this is used (pretty much in the example shown right at the start of this article) and its length is checked. If the length is positive we know we can continue to the inner tests (if they exist) but if not we fail the test and don\u2019t go any further. We append the error to the test console for everyone to see.\n\nIf we pass the initial check we send the reference to the root element, message contains and the inner object to a function that in this example sends us on to confirm_html (if we had a more complex test suite it would do a lot more). \n\nconfirm_html\n\nconfirm_html:function(target_selector, error_elm, obj) {\n\tvar missing_elms = [];\n\t$.each(obj.elements, function(i, val) {\n\t\tif (!target_selector.find(val).length) {\n\t\t\tmissing_elms.push(val);\n\t\t}\t\n\t});\n\tif (missing_elms.length) {\n\t\tvar file_list = missing_elms.join('\n\t\t | \n\t |
\n\t\t\tYour email code goes here.\n\t\t | \n\t