Browse Source

html5fallback

euromark 14 years ago
parent
commit
e91d96f7b5
1 changed files with 161 additions and 0 deletions
  1. 161 0
      webroot/js/jquery.html5autofallback.js

+ 161 - 0
webroot/js/jquery.html5autofallback.js

@@ -0,0 +1,161 @@
+/**
+ * JS-Fallback for some new HTML5 features
+ * - placeholder (by Mark)
+ * - details (by Mathias)
+ * @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 = '<summary>a</summary>b';
+	 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('<span>');
+		 // 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 `<details>` yet
+		// Other browsers without `<details>` 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();
+		});
+	}
+
+})();
+