add latest loader.js

This commit is contained in:
Michael Deal 2012-11-21 01:30:04 -08:00
parent 26f6e8a031
commit 50eb9cb6eb

View file

@ -1,151 +1,329 @@
/*
----------------------------------------------------
Loader.js : 0.3 : 2012/04/12
Loader.js : 0.4.2 : 2012/11/09
----------------------------------------------------
https://github.com/mudcube/Loader.js
----------------------------------------------------
var loader = new widgets.Loader({ message: "loading: New loading message..." });
----------------------------------------------------
/// Simple setup.
var loader = new widgets.Loader;
/// More complex setup.
var loader = new widgets.Loader({
id: "loader",
bars: 12,
radius: 0,
lineWidth: 20,
lineHeight: 70,
timeout: 30, // maximum timeout in seconds.
background: "rgba(0,0,0,0.5)",
message: "loading...",
callback: function() {
container: document.body,
oncomplete: function() {
// call function once loader has completed
},
onstart: function() {
// call function once loader has started
}
});
loader.stop();
----------------------------------------------------
loader.message("loading: New loading message...", function() {
// call function once loader has started
/// Add a new message to the queue.
var loaderId = loader.add({
message: "test",
getProgress: function() { // sends progress to loader.js
return progress; // value between 1-100
}
});
/// Remove a specific loader message.
loader.remove(loaderId);
/// Recenter the loader within container (run onresize)
loader.center();
/// Stop all loader instances.
loader.stop();
*/
if (typeof(widgets) === "undefined") var widgets = {};
if (typeof (widgets) === "undefined") var widgets = {};
widgets.Loader = (function(root) { "use strict";
(function() { "use strict";
var PI = Math.PI;
var defaultConfig = {
var noCanvas = !document.createElement("canvas").getContext;
var fadeOutSpeed = 400;
var defaultConfig = {
id: "loader",
bars: 12,
radius: 0,
lineWidth: 20,
lineHeight: 70,
timeout: 0,
display: true
};
var getWindowSize = function() {
if (window.innerWidth && window.innerHeight) {
var width = window.innerWidth;
var height = window.innerHeight;
} else if (document.compatMode === 'CSS1Compat' && document.documentElement && document.documentElement.offsetWidth) {
var width = document.documentElement.offsetWidth;
var height = document.documentElement.offsetHeight;
} else if (document.body && document.body.offsetWidth) {
var width = document.body.offsetWidth;
var height = document.body.offsetHeight;
}
return {
width: width,
height: height
};
};
widgets.Loader = function (configure) {
if (noCanvas) return;
var that = this;
if (typeof (configure) === "string") configure = { message: configure };
if (typeof (configure) === "boolean") configure = { display: false };
if (typeof (configure) === "undefined") configure = {};
configure.container = configure.container || document.body;
if (!configure.container) return;
return function (conf) {
var that = this;
if (!document.createElement("canvas").getContext) return;
var that = this;
if (!document.body) return;
if (typeof(conf) === "string") conf = { message: conf };
if (typeof(conf) === "undefined") conf = {};
if (typeof(conf) === "boolean") conf = { display: false };
/// Mixin the default configurations.
for (var key in defaultConfig) {
if (typeof(conf[key]) === "undefined") {
conf[key] = defaultConfig[key];
if (typeof (configure[key]) === "undefined") {
configure[key] = defaultConfig[key];
}
}
//
function centerSpan() {
if (conf.message) {
var windowSize = getWindowSize();
var width = windowSize.width - size;
var height = windowSize.height - size;
that.span.style.left = ((width + size) / 2 - that.span.offsetWidth/2) + "px";
that.span.style.top = (height / 2 + size - 10) + "px";
}
};
///
var canvas = document.getElementById(conf.id);
var timeout = 1;
/// Setup element
var canvas = document.getElementById(configure.id);
if (!canvas) {
var div = document.createElement("div");
var span = document.createElement("span");
span.className = "message";
div.appendChild(span);
div.className = defaultConfig.id;
that.span = span;
that.div = div;
div.style.cssText = transitionCSS("opacity", fadeOutSpeed);
this.span = span;
this.div = div;
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.id = conf.id;
canvas.id = configure.id;
canvas.style.cssText = "opacity: 1; position: absolute; z-index: 10000;";
div.appendChild(canvas);
document.body.appendChild(div);
configure.container.appendChild(div);
} else {
that.span = canvas.parentNode.getElementsByTagName("span")[0];
this.span = canvas.parentNode.getElementsByTagName("span")[0];
}
//
var delay = conf.delay;
var bars = conf.bars;
var radius = conf.radius;
var max = conf.lineHeight + 20;
var size = max * 2 + conf.radius * 2;
var windowSize = getWindowSize();
/// Configure
var delay = configure.delay;
var bars = configure.bars;
var radius = configure.radius;
var max = configure.lineHeight + 20;
var size = max * 2 + configure.radius * 2;
var windowSize = getWindowSize(configure.container);
var width = windowSize.width - size;
var height = windowSize.height - size;
var deviceRatio = window.devicePixelRatio || 1;
///
canvas.width = size;
canvas.height = size;
canvas.style.left = (width / 2) + "px";
canvas.style.top = (height / 2) + "px";
canvas.width = size * deviceRatio;
canvas.height = size * deviceRatio;
///
centerSpan();
///
var offset = 0;
var ctx = canvas.getContext('2d');
var iteration = 0;
var ctx = canvas.getContext("2d");
ctx.globalCompositeOperation = "lighter";
ctx.shadowOffsetX = 1;
ctx.shadowOffsetY = 1;
ctx.shadowBlur = 1;
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
//
function animate() {
var windowSize = getWindowSize();
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
/// Public functions.
this.messageId;
this.messages = {};
this.message = function (message, onstart) {
if (!this.interval) return this.start(onstart, message);
if (this.messageId) return this.update(this.messageId, message);
return this.messageId = this.add({
message: message,
onstart: onstart
});
};
this.update = function(id, message, percent) {
var item = this.messages[id];
item.message = message;
if (typeof(percent) === "number") item.span.innerHTML = percent + "%";
if (message.substr(-3) === "...") { // animated dots
item._message = message.substr(0, message.length - 3);
item.messageAnimate = [".  ", ".. ", "..."].reverse();
} else { // normal
item._message = message;
item.messageAnimate = false;
}
///
item.element.innerHTML = message;
};
this.add = function (conf) {
if (typeof(conf) === "string") conf = { message: conf };
var background = configure.background ? configure.background : "rgba(0,0,0,0.65)";
this.span.style.cssText = "background: " + background + ";";
this.div.style.cssText = transitionCSS("opacity", fadeOutSpeed);
if (this.stopPropagation) {
this.div.style.cssText += "background: rgba(0,0,0,0.25);";
} else {
this.div.style.cssText += "pointer-events: none;";
}
///
canvas.parentNode.style.opacity = 1;
canvas.parentNode.style.display = "block";
if (configure.background) this.div.style.background = configure.backgrond;
///
var timestamp = (new Date()).getTime();
var seed = Math.abs(timestamp * Math.random() >> 0);
var message = conf.message;
///
var container = document.createElement("div");
container.style.cssText = transitionCSS("opacity", 500);
var span = document.createElement("span");
span.style.cssText = "float: right; width: 50px;";
var node = document.createElement("span");
node.innerHTML = message;
///
container.appendChild(node);
container.appendChild(span);
///
var item = this.messages[seed] = {
seed: seed,
container: container,
element: node,
span: span,
message: message,
timeout: (conf.timeout || configure.timeout) * 1000,
timestamp: timestamp,
getProgress: conf.getProgress
};
this.span.appendChild(container);
this.span.style.display = "block";
this.update(item.seed, message);
this.center();
/// Escape event loop.
if (conf.onstart) {
window.setTimeout(conf.onstart, 50);
}
///
this.center();
///
if (!this.interval) {
if (!conf.delay) renderAnimation();
window.clearInterval(this.interval);
this.interval = window.setInterval(renderAnimation, 30);
}
/// Return identifier.
return seed;
};
this.remove = function (seed) {
iteration += 0.07;
var timestamp = (new Date()).getTime();
if (typeof(seed) === "object") seed = seed.join(":");
if (seed) seed = ":" + seed + ":";
/// Remove element.
for (var key in this.messages) {
var item = this.messages[key];
if (!seed || seed.indexOf(":" + item.seed + ":") !== -1) {
delete this.messages[item.seed];
item.container.style.color = "#99ff88";
removeChild(item);
if (item.getProgress) item.span.innerHTML = "100%";
}
}
};
this.start = function (onstart, message) {
if (!(message || configure.message)) return;
return this.messageId = this.add({
message: message || configure.message,
onstart: onstart
});
};
this.stop = function () {
this.remove();
window.clearInterval(this.interval);
delete this.interval;
if (configure.oncomplete) configure.oncomplete();
if (canvas && canvas.style) {
div.style.cssText += "pointer-events: none;";
window.setTimeout(function() {
that.div.style.opacity = 0;
}, 1);
window.setTimeout(function () {
if (that.interval) return;
that.stopPropagation = false;
canvas.parentNode.style.display = "none";
ctx.clearRect(0, 0, size, size);
}, fadeOutSpeed * 1000);
}
};
this.center = function() {
var windowSize = getWindowSize(configure.container);
var width = windowSize.width - size;
var height = windowSize.height - size;
//
/// Center the animation within the content.
canvas.style.left = (width / 2) + "px";
canvas.style.top = (height / 2) + "px";
centerSpan();
canvas.style.width = (size) + "px";
canvas.style.height = (size) + "px";
that.span.style.left = ((width + size) / 2 - that.span.offsetWidth / 2) + "px";
that.span.style.top = (height / 2 + size - 10) + "px";
};
var style = document.createElement("style");
style.innerHTML = '\
.loader { color: #fff; position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 100000; opacity: 0; display: none; }\
.loader span.message { font-family: monospace; font-size: 14px; opacity: 1; display: none; border-radius: 10px; padding: 0px; width: 300px; text-align: center; position: absolute; z-index: 10000; }\
.loader span.message div { border-bottom: 1px solid #222; padding: 5px 10px; clear: both; text-align: left; opacity: 1; }\
.loader span.message div:last-child { border-bottom: none; }\
';
document.head.appendChild(style);
/// Private functions.
var removeChild = function(item) {
window.setTimeout(function() { // timeout in case within same event loop.
item.container.style.opacity = 0;
}, 1);
window.setTimeout(function() { // wait for opacity=0 before removing the element.
item.container.parentNode.removeChild(item.container);
}, 10);
};
var renderAnimation = function () {
var timestamp = (new Date()).getTime();
for (var key in that.messages) {
var item = that.messages[key];
var nid = iteration / 0.07 >> 0;
if (nid % 5 === 0 && item.getProgress) {
if (item.timeout && item.timestamp && timestamp - item.timestamp > item.timeout) {
that.remove(item.seed);
continue;
}
var progress = item.getProgress();
if (progress >= 100) {
that.remove(item.seed);
continue;
}
item.span.innerHTML = (progress >> 0) + "%";
}
if (nid % 10 === 0) {
if (item.messageAnimate) {
var length = item.messageAnimate.length;
var n = nid / 10 % length;
var text = item._message + item.messageAnimate[n];
item.element.innerHTML = text;
}
}
}
if (!key) {
that.stop();
}
//
ctx.save();
ctx.clearRect(0, 0, size, size);
ctx.clearRect(0, 0, size * deviceRatio, size * deviceRatio);
ctx.scale(deviceRatio, deviceRatio);
ctx.translate(size / 2, size / 2);
var hues = 360 - 360 / bars;
for (var i = 0; i < bars; i++) {
var angle = (i / bars * 2 * PI) + offset;
var angle = (i / bars * 2 * PI) + iteration;
ctx.save();
ctx.translate(radius * Math.sin(-angle), radius * Math.cos(-angle));
ctx.rotate(angle);
// round-rect properties
var x = -conf.lineWidth / 2;
var x = -configure.lineWidth / 2;
var y = 0;
var width = conf.lineWidth;
var height = conf.lineHeight;
var width = configure.lineWidth;
var height = configure.lineHeight;
var curve = width / 2;
// round-rect path
ctx.beginPath();
@ -165,87 +343,48 @@ return function (conf) {
ctx.restore();
}
ctx.restore();
offset += 0.07;
//
if (conf.messageAnimate) {
var iteration = offset / 0.07 >> 0;
if (iteration % 10 === 0) {
var length = conf.messageAnimate.length;
var n = iteration / 10 % length;
that.span.innerHTML = conf.message + conf.messageAnimate[n];
}
}
};
this.css = function() {
var background = conf.background ? conf.background : "rgba(0,0,0,0.65)";
span.style.cssText = "font-family: monospace; font-size: 14px; opacity: 1; display: none; background: "+background+"; border-radius: 10px; padding: 10px; width: 200px; text-align: center; position: absolute; z-index: 10000;";
div.style.cssText = "color: #fff; -webkit-transition-property: opacity; -webkit-transition-duration: " + timeout + "s; position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 100000; opacity: 0; display: none";
if (this.stopPropagation) {
div.style.cssText += "background: rgba(0,0,0,0.25);";
} else {
div.style.cssText += "pointer-events: none;";
}
};
this.stop = function () {
setTimeout(function() {
window.clearInterval(that.interval);
delete that.interval;
}, 50);
if (canvas && canvas.style) {
div.style.cssText += "pointer-events: none;";
canvas.parentNode.style.opacity = 0;
window.setTimeout(function () {
that.stopPropagation = false;
canvas.parentNode.style.display = "none";
ctx.clearRect(0, 0, size, size);
}, timeout * 1000);
}
};
this.start = function (callback) {
this.css();
var windowSize = getWindowSize();
var width = windowSize.width - size;
var height = windowSize.height - size;
canvas.parentNode.style.opacity = 1;
canvas.parentNode.style.display = "block";
that.span.style.display = conf.message ? "block" : "none";
if (conf.background) that.div.style.background = conf.backgrond;
canvas.style.left = (width / 2) + "px";
canvas.style.top = (height / 2) + "px";
if (!conf.delay) animate();
window.clearInterval(this.interval);
this.interval = window.setInterval(animate, 30);
if (conf.message) {
compileMessage(conf.message, callback);
}
};
this.message = function(message, callback) {
conf.message = message;
if (!this.interval) return this.start(callback);
if (conf.background) that.span.style.background = conf.backgrond;
compileMessage(conf.message, callback);
that.span.style.display = conf.message ? "block" : "none";
};
var compileMessage = function(message, callback) {
if (message.substr(-3) === "...") {
conf.message = message.substr(0, message.length - 3);
conf.messageAnimate = [ ".&nbsp;&nbsp;","..&nbsp;","..." ].reverse();
that.span.innerHTML = conf.message + conf.messageAnimate[0];
} else {
conf.messageAnimate = false;
that.span.innerHTML = conf.message;
}
if (callback) {
setTimeout(callback, 50);
}
iteration += 0.07;
};
//
if (conf.display === false) return this;
if (configure.display === false) return this;
//
this.css();
this.start();
//
return this;
};
})(widgets);
////
var transitionCSS = function(type, ms) {
return '\
-webkit-transition-property: '+type+';\
-webkit-transition-duration: '+ms+'ms;\
-moz-transition-property: '+type+';\
-moz-transition-duration: '+ms+'ms;\
-o-transition-property: '+type+';\
-o-transition-duration: '+ms+'ms;\
-ms-transition-property: '+type+';\
-ms-transition-duration: '+ms+'ms;';
};
var getWindowSize = function (element) {
if (window.innerWidth && window.innerHeight) {
var width = window.innerWidth;
var height = window.innerHeight;
} else if (document.compatMode === "CSS1Compat" && document.documentElement && document.documentElement.offsetWidth) {
var width = document.documentElement.offsetWidth;
var height = document.documentElement.offsetHeight;
} else if (document.body && document.body.offsetWidth) {
var width = document.body.offsetWidth;
var height = document.body.offsetHeight;
}
if (element) {
var width = element.offsetWidth;
}
return {
width: width,
height: height
};
};
})();