Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<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>
Expand Down Expand Up @@ -44,7 +43,7 @@ <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>Supports 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>
Expand All @@ -56,7 +55,7 @@ <h2>Browser support</h2>
<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.
<p>Just add <code>progress-polyfill.js</code> near the body closing tag.</p>

<h2>Unit tests</h2>
<p style="display:none">
Expand All @@ -71,4 +70,4 @@ <h2>Unit tests</h2>
<script src="progress-polyfill.js"></script>
<script src="tests.js"></script>
</body>
</html>
</html>
102 changes: 96 additions & 6 deletions progress-polyfill.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
/*
* <progress> polyfill
* Don't forget to also include progress-polyfill.css!
* You may need to change
* @author Lea Verou
*/

(function(){

// The location of the polyfill stylesheet
var CSS_FILE = 'progress-polyfill.css';

// Test browser support first
if('position' in document.createElement('progress')) {
return;
}

// Load the progress-polyfill.css file dynamically only
// if needed for the polyfill
var cssElem = document.createElement('link');
cssElem.rel = 'stylesheet';
cssElem.type = 'text/css';
cssElem.href = CSS_FILE;
document.getElementsByTagName('head')[0].appendChild(cssElem);

/**
* Private functions
*/
Expand Down Expand Up @@ -39,6 +50,7 @@ if (!defineProperty) {
}
}

// Get a function arr() for casting NodeList to Array
try {
[].slice.apply(document.images)

Expand All @@ -64,6 +76,35 @@ var attrsAsProps = (function(){
return e.getAttribute('foo') === 'bar';
})();

// Parses an outerHTML string to get the attributes section
// of a progress tag and allows selecting individual attributes
var getAttr = (function() {
var
regexes = { },
whitespace = /\s+/,
getAttributes = /<progress([^>]+)/;
return function(elem, attr) {
var outer = (typeof elem === 'string') ? elem : elem.outerHTML;
if (outer) {
var attrs = getAttributes.exec(outer);
if (attrs) {
attrs = attrs[1];
if (! regexes[attr]) {
regexes[attr] = new RegExp('\\s+' + attr + '=(.+)(\\s|$)');
}
var value = regexes[attr].exec(attrs);
if (value) {
value = value[1].split(whitespace)[0];
if (value.charAt(0) === '"' || value.charAt(0) === "'") {
value = value.substring(1, value.length - 1);
}
}
return value;
}
}
};
}());

var self = window.ProgressPolyfill = {
DOMInterface: {
max: {
Expand All @@ -73,7 +114,7 @@ var self = window.ProgressPolyfill = {

set: function(value) {
this.setAttribute('aria-valuemax', value);

if(!attrsAsProps) {
this.setAttribute('max', value);
}
Expand Down Expand Up @@ -155,7 +196,11 @@ var self = window.ProgressPolyfill = {
if(self.isInited(progress)) {
return; // Already init-ed
}


// Get initial attributes if they exist
var initialMax = getAttr(progress, 'max');
var initialValue = getAttr(progress, 'value');

// Add ARIA
progress.setAttribute('role', 'progressbar');
progress.setAttribute('aria-valuemin', '0');
Expand All @@ -172,6 +217,53 @@ var self = window.ProgressPolyfill = {
set: self.DOMInterface[attribute].set
});
}

// Fix (get|set|remove)Attribute in IE
if (
(initialMax && progress.getAttribute('max') !== initialMax) ||
(initialValue && progress.getAttribute('value') !== initialValue)
) {
var
_attributes = { },
proto = progress.constructor.prototype;
// Fix setAttribute
progress.setAttribute = function(attr, value) {
_attributes[attr] = String(value);
proto.setAttribute.call(progress, attr, value);
};
progress.setAttribute.toString = function() {
proto.setAttribute + '';
};
// Fix getAttribute
progress.getAttribute = function(attr) {
var value = proto.getAttribute.call(progress, attr);
if (value === null && (attr === 'max' || attr === 'value')) {
value = getAttr(progress, attr);
if (value === null) {
value = _attributes[attr] || null;
}
}
return value;
};
progress.getAttribute.toString = function() {
proto.getAttribute + '';
};
// Fix remove attribute
progress.removeAttribute = function(attr) {
_attributes[attr] = null;
proto.removeAttribute.call(progress, attr);
};
progress.removeAttribute.toString = function() {
proto.removeAttribute + '';
};
}

if (initialMax) {
progress.setAttribute('max', initialMax);
}
if (initialValue) {
progress.setAttribute('value', initialValue);
}

self.redraw(progress);
},
Expand All @@ -180,8 +272,6 @@ var self = window.ProgressPolyfill = {
progresses: document.getElementsByTagName('progress')
};



for(var i=self.progresses.length-1; i>=0; i--) {
self.init(self.progresses[i]);
}
Expand All @@ -205,4 +295,4 @@ if(document.addEventListener) {
}, false);
}

})();
})();
2 changes: 1 addition & 1 deletion tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ assert('add new progress, get position property', function(){
var ret = p.position;
document.body.removeChild(p);
return ret;
}, 30/100, 'mutation+etters');
}, 30/100, 'mutation+etters');