Permalink
Browse files

Initial import

  • Loading branch information...
0 parents commit cf4022a33f6b2b3c375ad825a6f5ae5a4246dafe Lea Verou committed Jul 2, 2011
Showing with 477 additions and 0 deletions.
  1. +74 −0 index.html
  2. +47 −0 progress-polyfill.css
  3. +201 −0 progress-polyfill.js
  4. +72 −0 style.css
  5. +83 −0 tests.js
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+
+<meta charset="utf-8" />
+<title>HTML5 &lt;progress&gt; polyfill by Lea Verou</title>
+<link href="style.css" rel="stylesheet" />
+<link href="progress-polyfill.css" rel="stylesheet" />
+<script>document.createElement('progress');</script>
+</head>
+<body>
+ <hgroup>
+ <h1>HTML5 &lt;progress&gt; polyfill</h1>
+ <h2><a href="http://leaverou.me">by Lea Verou</a></h2>
+ </hgroup>
+
+ <h2>Demos</h2>
+ <ul>
+ <li>
+ <label>Indeterminate
+ <progress max="100"></progress>
+ </label>
+ </li>
+ <li>
+ <label for="progress1">Progress: 0%</label>
+ <progress max="10" value="0" id="progress1"></progress>
+ </li>
+ <li>
+ <label for="progress2">Progress: .5 of 0</label>
+ <progress max="0" value="0.5" id="progress2"></progress>
+ </li>
+ <li>
+ <label for="progress3">Progress: 100%</label>
+ <progress max="3254" value="3254" id="progress3"></progress>
+ </li>
+ <li>
+ <label>Progress: 75%
+ <progress max="0.8" value="0.6"></progress>
+ </label>
+ </li>
+ </ul>
+
+ <h2>Features</h2>
+ <ul>
+ <li>Accessible (WAI-ARIA-enabled)</li>
+ <li>Supports getting (and setting, when allowed by the spec) all the IDL attributes defined in the specification (value, max, position, labels), through ES5 getters and setters</li>
+ <li>Supoorts setting both max and value attributes, through mutation events</li>
+ <li>Will fix new progress elements as well, through mutation events</li>
+ <li>No extra HTML elements needed and none added through script</li>
+ </ul>
+
+ <h2>Browser support</h2>
+ <p>The progress element is natively supported in: Firefox 6+, Opera 11+, Chrome, Safari 5.1</p>
+ <p>This polyfill adds almost full support in: Firefox 3.5-5, Opera 10.5-10.63, IE9-10</p>
+ <p>This polyfill adds partial support in: IE8</p>
+ <p>Supporting Safari 5 was impossible, as it completely drops the progress tags and gives you an error</p>
+
+ <h2>How to use</h2>
+ <p>Just add <code>progress-polyfill.css</code> in the head section and <code>progress-polyfill.js</code> near the body closing tag.
+
+ <h2>Unit tests</h2>
+ <p style="display:none">
+ <label><progress max="0.8" value="0.6" id="progress4"></progress></label>
+ <label for="progress4">Test label for progress4</label>
+ <progress max="100" id="progress0"></progress>
+ <progress max="0" id="progress5"></progress>
+ </p>
+
+ <div id="unit-test-results"></div>
+
+ <script src="progress-polyfill.js"></script>
+ <script src="tests.js"></script>
+</body>
+</html>
@@ -0,0 +1,47 @@
+progress[role] {
+ display: inline-block;
+ position: relative;
+ width: 10em;
+ height: 1em;
+ vertical-align: -.2em;
+ background-image: url('data:image/gif;base64,R0lGODlhIAAQAIABAP///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowMTgwMTE3NDA3MjA2ODExODE3QTgyOEM0MzAwRkUyMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3NEY2MUMyQTlDMzgxMUUwOUFFQ0M4MEYwM0YzNUE2RCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3NEY2MUMyOTlDMzgxMUUwOUFFQ0M4MEYwM0YzNUE2RCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE4MTdBODI4QzQzMDBGRTIzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4MTE4MTdBODI4QzQzMDBGRTIzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkECQoAAQAsAAAAACAAEAAAAiwMjqkQ7Q/bmijaR+ndee7bLZ8VKmNUJieUVqvTHi8cz1Jtx0yOz7pt6L10BQAh+QQJCgABACwAAAAAIAAQAAACLYwNqctwD2GbKtpH6d157ts1nxUyY1Qup5QmK9Y6LxLPdGsHsTvv8uuzBXuhAgAh+QQJCgABACwAAAAAIAAQAAACLIx/oMsNCKNxdMk7K8VXbx55DhiKDAmZJ5qoFhu4LysrcFzf9QPvet4D0igFACH5BAkKAAEALAAAAAAgABAAAAIsjI8Hy+2QYnyUyWtqxVdvnngUGIoOiZgnmqkWG7gvKy9wXN81BO963gPSGAUAIfkECQoAAQAsAAAAACAAEAAAAixEjqkB7Q/bmijaR+ndee7bLZ8VKmNUJieUVqvTHi8cz1Jtx0yOz7pt6L10BQAh+QQJCgABACwAAAAAIAAQAAACLYQdqctxD2GbKtpH6d157ts1nxUyY1Qup5QmK9Y6LxLPdGsDsTvv8uuzBXuhAgAh+QQJCgABACwAAAAAIAAQAAACLIR/ocsdCKNxdMk7K8VXbx55DhiKDAmZJ5qoFgu4LysrcFzf9QPvet4D0igFACH5BAUKAAEALAAAAAAgABAAAAIshI8Xy+2RYnyUyWtqxVdvnngUGIoOiZgnmqkWC7gvKy9wXN81BO963gPSGAUAOw==');
+
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+progress[role],
+progress[aria-valuenow]:before {
+ background-color: #5af;
+}
+
+progress[role],
+progress[role]:after {
+ background-repeat:repeat-x;
+ background-position: 0 0;
+ -moz-background-size: auto 100%;
+ -webkit-background-size: auto 100%;
+ background-size: auto 100%;
+}
+
+/* Determinate only overrides */
+progress[aria-valuenow] {
+ background: #eee;
+}
+
+progress[aria-valuenow]:before {
+ content: "";
+ display: block;
+ height: 100%;
+}
+
+/* Overlay */
+progress[role]:after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA6lpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFRTE5QjlCQTlDMkQxMUUwOUFFQ0M4MEYwM0YzNUE2RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNkRFQUIzNjlDMkUxMUUwOUFFQ0M4MEYwM0YzNUE2RCI+IDxkYzp0aXRsZT4gPHJkZjpBbHQ+IDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+Z3JhZGllbnQ8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFRTE5QjlCODlDMkQxMUUwOUFFQ0M4MEYwM0YzNUE2RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFRTE5QjlCOTlDMkQxMUUwOUFFQ0M4MEYwM0YzNUE2RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pq477Q0AAAD2SURBVHjaxFIxDsIwDLRF/1AmRp7AM9iYWHkD76AP6h9Qi1SGfqAMqGJg6XA4jts0RUwZiKLEsZ3L+Rwmoi0lDC6Ky4rAMuGO5DY5iuWH93oDegMuK8QA7JIYCMDpvwDDMBzNHCGtONYq2enjHKYLMObCp7dtu/+FDppDgyJpTemsrm/9l7L2ku4aUy4BTEmKR1hmVXV9OjfsqlqC7irAhBKxDnmOQdPc+ynKMXdenEELAFmzrnu8RoK6jpRhHkGJmFgdXmsByNf5Wx+fJPbigEI3OKrB77Bfy2VZzppqC0IfAtlIAusC9CNtUn/iIRXgnALwEWAA/+5+ZNOapmcAAAAASUVORK5CYII=');
+}
@@ -0,0 +1,201 @@
+/*
+ * <progress> polyfill
+ * Don't forget to also include progress-polyfill.css!
+ * @author Lea Verou
+ */
+
+(function(){
+
+// Test browser support first
+if('position' in document.createElement('progress')) {
+ return;
+}
+
+/**
+ * Private functions
+ */
+
+// Smoothen out differences between Object.defineProperty
+// and __defineGetter__/__defineSetter__
+var defineProperty = Object.defineProperty,
+ supportsEtters = true;
+
+if (!defineProperty) {
+ if ('__defineSetter__' in progress) {
+ defineProperty = function(o, property, etters) {
+ o.__defineGetter__(property, etters.get);
+
+ if(etters.set) {
+ o.__defineSetter__(property, etters.set);
+ }
+ };
+ }
+ else {
+ // Fallback to regular properties if getters/setters are not supported
+ defineProperty = function(o, property, etters) {
+ o[property] = etters.get();
+ },
+ supportsEtters = false;
+ }
+}
+
+try {
+ [].slice.apply(document.images)
+
+ var arr = function(collection) {
+ return [].slice.apply(collection);
+ }
+} catch(e) {
+ var arr = function(collection) {
+ var ret = [], len = collection.length;
+
+ for(var i=0; i<len; i++) {
+ ret[i] = collection[i];
+ }
+
+ return ret;
+ }
+}
+
+// Does the browser use attributes as properties? (IE8- bug)
+var attrsAsProps = (function(){
+ var e = document.createElement('div');
+ e.foo = 'bar';
+ return e.getAttribute('foo') === 'bar';
+})();
+
+var self = window.ProgressPolyfill = {
+ DOMInterface: {
+ max: {
+ get: function(){
+ return parseFloat(this.getAttribute('aria-valuemax')) || 1;
+ },
+
+ set: function(value) {
+ this.setAttribute('aria-valuemax', value);
+
+ if(!attrsAsProps) {
+ this.setAttribute('max', value);
+ }
+
+ self.redraw(this);
+ }
+ },
+
+ value: {
+ get: function(){
+ return parseFloat(this.getAttribute('aria-valuenow')) || 0;
+ },
+
+ set: function(value) {
+ this.setAttribute('aria-valuenow', value);
+
+ if(!attrsAsProps) {
+ this.setAttribute('value', value);
+ }
+
+ self.redraw(this);
+ }
+ },
+
+ position: {
+ get: function(){
+ return this.hasAttribute('aria-valuenow')? this.value/this.max : -1;
+ }
+ },
+
+ labels: {
+ get: function(){
+ var label = this.parentNode;
+
+ while(label && label.nodeName !== 'LABEL') {
+ label = label.parentNode;
+ }
+
+ var labels = label? [label] : [];
+
+ if(this.id && document.querySelectorAll) {
+ var forLabels = arr(document.querySelectorAll('label[for="' + this.id + '"]'));
+
+ if(forLabels.length) {
+ labels = labels.concat(forLabels);
+ }
+ }
+
+ return labels;
+ }
+ }
+ },
+
+ redraw: function redraw(progress) {
+ if(!attrsAsProps) {
+ progress.setAttribute('aria-valuemax', parseFloat(progress.getAttribute('max')) || 1);
+
+ if(progress.hasAttribute('value')) {
+ progress.setAttribute('aria-valuenow', parseFloat(progress.getAttribute('value')) || 0);
+ }
+ else {
+ progress.removeAttribute('aria-valuenow');
+ }
+ }
+
+ if(progress.position !== -1) {
+ progress.style.paddingRight = progress.offsetWidth * (1-progress.position) + 'px';
+ }
+ },
+
+ init: function (progress) {
+ if(progress.getAttribute('role') === 'progressbar') {
+ return; // Already init-ed
+ }
+
+ // Add ARIA
+ progress.setAttribute('role', 'progressbar');
+ progress.setAttribute('aria-valuemin', '0');
+ progress.setAttribute('aria-valuemax', parseFloat(progress.getAttribute('max')) || 1);
+
+ if(progress.hasAttribute('value')) {
+ progress.setAttribute('aria-valuenow', parseFloat(progress.getAttribute('value')) || 0);
+ }
+
+ // We can't add them on a prototype, as it's the same for all unknown elements
+ for(var attribute in self.DOMInterface) {
+ defineProperty(progress, attribute, {
+ get: self.DOMInterface[attribute].get,
+ set: self.DOMInterface[attribute].set
+ });
+ }
+
+ progress.addEventListener
+ && progress.addEventListener('DOMAttrModified', function(evt) {
+ var attribute = evt.attrName;
+
+ if(attribute == 'max' || attribute == 'value') {
+ self.redraw(this);
+ }
+ }, false);
+
+ self.redraw(progress);
+ },
+
+ // Live NodeList, will update automatically
+ progresses: document.getElementsByTagName('progress')
+};
+
+
+
+for(var i=self.progresses.length-1; i>=0; i--) {
+ self.init(self.progresses[i]);
+}
+
+// Take care of future ones too, if supported
+document.addEventListener
+ && document.addEventListener('DOMNodeInserted', function(evt) {
+ var node = evt.target;
+
+ if(node.nodeName === 'PROGRESS') {
+ self.init(node);
+ }
+ }, false);
+
+})();
Oops, something went wrong.

0 comments on commit cf4022a

Please sign in to comment.