/** * JS-Fallback for some new HTML5 features * - placeholder (by Mark) * - details (by Mathias) * * Requires: * - jquery1.6 (maybe less) * - jquery.livequery to work with ajax content * * @author Mark Scherer * @licence MIT * 2011-11-29 ms */ (function() { /* placeholder */ var input = document.createElement('input'); if(!('placeholder' in input)) { $('input[placeholder], textarea[placeholder]').livequery(function() { var obj = $(this); var setPlaceholder = function() { if (!obj.val() || obj.val() == obj.attr('placeholder')) { obj.val(obj.attr('placeholder')).addClass('pseudoPlaceholder').data('fallbackPlaceholder', true); } } setPlaceholder(); var unsetPlaceholder = function() { obj.val('').removeClass('pseudoPlaceholder').data('fallbackPlaceholder', false); } obj.blur(function() { if(!obj.val().length) { setPlaceholder(); } }); obj.focus(function() { if(obj.data('fallbackPlaceholder')) { unsetPlaceholder(); } }); }); $('form').live('submit', function() { $(this).find(".pseudoPlaceholder").each(function() { var obj = $(this); obj.removeClass('pseudoPlaceholder'); if (!obj.val() || obj.val() == obj.attr('placeholder')) { obj.val(''); }; }); }); } if(!('autofocus' in input)) { $('input[autofocus], textarea[placeholder]').livequery(function() { $(this).focus(); }); } /* details - http://mathiasbynens.be/notes/html5-details-jquery */ var isDetailsSupported = (function(doc) { var el = doc.createElement('details'), de = doc.documentElement, fake, root = doc.body || (function() { fake = true; return de.insertBefore(doc.createElement('body'), de.firstChildElement || de.firstChild); }()), diff; el.innerHTML = 'ab'; el.style.display = 'block'; root.appendChild(el); diff = el.offsetHeight; el.open = true; diff = diff != el.offsetHeight; root.removeChild(el); if (fake) { root.parentNode.removeChild(root); } return diff; }(document)); // Execute the fallback only if there’s no native `details` support if (!isDetailsSupported) { document.documentElement.className += ' no-details'; // Loop through all `details` elements $('details').each(function() { // Store a reference to the current `details` element in a variable var $details = $(this), // Store a reference to the `summary` element of the current `details` element (if any) in a variable $detailsSummary = $('summary', $details), // Do the same for the info within the `details` element $detailsNotSummary = $details.children(':not(summary)'), // This will be used later to look for direct child text nodes $detailsNotSummaryContents = $details.contents(':not(summary)'), // This will be used later on open; // If there is no `summary` in the current `details` element… if (!$detailsSummary.length) { // …create one with default text $detailsSummary = $(document.createElement('summary')).text('Details').prependTo($details); } // Look for direct child text nodes if ($detailsNotSummary.length !== $detailsNotSummaryContents.length) { // Wrap child text nodes in a `span` element $detailsNotSummaryContents.filter(function() { // Only keep the node in the collection if it’s a text node containing more than only whitespace return (this.nodeType === 3) && (/[^\t\n\r ]/.test(this.data)); }).wrap(''); // There are now no direct child text nodes anymore — they’re wrapped in `span` elements $detailsNotSummary = $details.children(':not(summary)'); } // Hide content unless there’s an `open` attribute // Chrome 10 already recognizes the `open` attribute as a boolean (even though it doesn’t support rendering `
` yet // Other browsers without `
` support treat it as a string /* fix - 2011-05-13 ms */ open = $details.get()[0].getAttribute('open'); if (typeof open == 'string' || (typeof open == 'boolean' && open)) { $details.addClass('open'); $detailsNotSummary.show(); } else { $detailsNotSummary.hide(); } // Set the `tabindex` attribute of the `summary` element to 0 to make it keyboard accessible $detailsSummary.attr('tabindex', 0).click(function() { // Focus on the `summary` element $detailsSummary.focus(); // Toggle the `open` attribute of the `details` element typeof $details.attr('open') !== 'undefined' ? $details.removeAttr('open') : $details.attr('open', 'open'); // Toggle the additional information in the `details` element $detailsNotSummary.toggle(0); $details.toggleClass('open'); }).keyup(function(event) { if (13 === event.keyCode || 32 === event.keyCode) { // Enter or Space is pressed — trigger the `click` event on the `summary` element // Opera already seems to trigger the `click` event when Enter is pressed if (!($.browser.opera && 13 === event.keyCode)) { event.preventDefault(); $detailsSummary.click(); } } }); }); } if(!('list' in input)) { $('input[list]').livequery(function() { $(this).datalist(); }); } })();