123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
-
- (function () {
- var headers = { "Etag": 1, "Last-Modified": 1, "Content-Length": 1, "Content-Type": 1 },
- resources = {},
- pendingRequests = {},
- currentLinkElements = {},
- oldLinkElements = {},
- interval = 1000,
- loaded = false,
- active = { "html": 1, "css": 1, "js": 1 };
-
- var Live = {
-
-
- heartbeat: function () {
- if (document.body) {
-
- if (!loaded) Live.loadresources();
- Live.checkForChanges();
- }
- setTimeout(Live.heartbeat, interval);
- },
-
-
- loadresources: function () {
-
-
- function isLocal(url) {
- var loc = document.location,
- reg = new RegExp("^\\.|^\/(?!\/)|^[\\w]((?!://).)*$|" + loc.protocol + "//" + loc.host);
- return url.match(reg);
- }
-
-
- var scripts = document.getElementsByTagName("script"),
- links = document.getElementsByTagName("link"),
- uris = [];
-
-
- for (var i = 0; i < scripts.length; i++) {
- var script = scripts[i], src = script.getAttribute("src");
- if (src && isLocal(src))
- uris.push(src);
- if (src && src.match(/\blive.js#/)) {
- for (var type in active)
- active[type] = src.match("[#,|]" + type) != null
- if (src.match("notify"))
- alert("Live.js is loaded.");
- }
- }
- if (!active.js) uris = [];
- if (active.html) uris.push(document.location.href);
-
-
- for (var i = 0; i < links.length && active.css; i++) {
- var link = links[i], rel = link.getAttribute("rel"), href = link.getAttribute("href", 2);
- if (href && rel && rel.match(new RegExp("stylesheet", "i")) && isLocal(href)) {
- uris.push(href);
- currentLinkElements[href] = link;
- }
- }
-
-
- for (var i = 0; i < uris.length; i++) {
- var url = uris[i];
- Live.getHead(url, function (url, info) {
- resources[url] = info;
- });
- }
-
-
- var head = document.getElementsByTagName("head")[0],
- style = document.createElement("style"),
- rule = "transition: all .3s ease-out;"
- css = [".livejs-loading * { ", rule, " -webkit-", rule, "-moz-", rule, "-o-", rule, "}"].join('');
- style.setAttribute("type", "text/css");
- head.appendChild(style);
- style.styleSheet ? style.styleSheet.cssText = css : style.appendChild(document.createTextNode(css));
-
-
- loaded = true;
- },
-
-
- checkForChanges: function () {
- for (var url in resources) {
- if (pendingRequests[url])
- continue;
-
- Live.getHead(url, function (url, newInfo) {
- var oldInfo = resources[url],
- hasChanged = false;
- resources[url] = newInfo;
- for (var header in oldInfo) {
-
- var oldValue = oldInfo[header],
- newValue = newInfo[header],
- contentType = newInfo["Content-Type"];
- switch (header.toLowerCase()) {
- case "etag":
- if (!newValue) break;
-
- default:
- hasChanged = oldValue != newValue;
- break;
- }
-
- if (hasChanged) {
- Live.refreshResource(url, contentType);
- break;
- }
- }
- });
- }
- },
-
-
- refreshResource: function (url, type) {
- switch (type.toLowerCase()) {
-
- case "text/css":
- var link = currentLinkElements[url],
- html = document.body.parentNode,
- head = link.parentNode,
- next = link.nextSibling,
- newLink = document.createElement("link");
-
- html.className = html.className.replace(/\s*livejs\-loading/gi, '') + ' livejs-loading';
- newLink.setAttribute("type", "text/css");
- newLink.setAttribute("rel", "stylesheet");
- newLink.setAttribute("href", url + "?now=" + new Date() * 1);
- next ? head.insertBefore(newLink, next) : head.appendChild(newLink);
- currentLinkElements[url] = newLink;
- oldLinkElements[url] = link;
-
-
- Live.removeoldLinkElements();
- break;
-
-
- case "text/html":
- if (Live.removeArgsId(url) != Live.removeArgsId(document.location.href))
- return;
-
-
- case "text/javascript":
- case "application/javascript":
- case "application/x-javascript":
- document.location.reload();
- }
- },
-
- removeArgsId: function(url){
- var idx = url.indexOf("?");
- if(idx >= 0){
- url = url.substr(0, idx);
- }
- idx = url.indexOf("#");
- if(idx >= 0){
- url = url.substr(0, idx);
- }
- return url;
- },
-
-
- removeoldLinkElements: function () {
- var pending = 0;
- for (var url in oldLinkElements) {
-
- try {
- var link = currentLinkElements[url],
- oldLink = oldLinkElements[url],
- html = document.body.parentNode,
- sheet = link.sheet || link.styleSheet,
- rules = sheet.rules || sheet.cssRules;
- if (rules.length >= 0) {
- oldLink.parentNode.removeChild(oldLink);
- delete oldLinkElements[url];
- setTimeout(function () {
- html.className = html.className.replace(/\s*livejs\-loading/gi, '');
- }, 100);
- }
- } catch (e) {
- pending++;
- }
- if (pending) setTimeout(Live.removeoldLinkElements, 50);
- }
- },
-
-
- getHead: function (url, callback) {
- pendingRequests[url] = true;
- var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XmlHttp");
- xhr.open("HEAD", url, true);
- xhr.onreadystatechange = function () {
- delete pendingRequests[url];
- if (xhr.readyState == 4 && xhr.status != 304) {
- xhr.getAllResponseHeaders();
- var info = {};
- for (var h in headers) {
- var value = xhr.getResponseHeader(h);
-
- if (h.toLowerCase() == "etag" && value) value = value.replace(/^W\//, '');
- if (h.toLowerCase() == "content-type" && value) value = value.replace(/^(.*?);.*?$/i, "$1");
- info[h] = value;
- }
- callback(url, info);
- }
- }
- xhr.send();
- }
- };
-
-
- if (document.location.protocol != "file:") {
- if (!window.liveJsLoaded)
- Live.heartbeat();
-
- window.liveJsLoaded = true;
- }
- else if (window.console)
- console.log("Live.js doesn't support the file protocol. It needs http.");
- })();
-
|