Commit bfef170d authored by epsi sayidina's avatar epsi sayidina

HTML Basic: 04-Webpack

parent 0b850504
......@@ -82,7 +82,7 @@ module.exports = function(grunt) {
// define the tasks
grunt.registerTask('default', [
'watch'
'pug', 'stylus', 'coffee', 'watch'
] );
};
......@@ -73,22 +73,19 @@
</style>
<script>
(function() {
document.addEventListener('DOMContentLoaded', function(event) {
var alertButtons, i;
alertButtons = document.getElementsByClassName('dismissable');
i = 0;
while (i < alertButtons.length) {
alertButtons[i].onclick = function() {
this.parentElement.style.display = 'none';
console.log('Close Button. Element ' + this.parentElement.id + ' dismissed');
return false;
};
i++;
}
});
}).call(this);
document.addEventListener('DOMContentLoaded', function(event) {
var alertButtons, i;
alertButtons = document.getElementsByClassName('dismissable');
i = 0;
while (i < alertButtons.length) {
alertButtons[i].onclick = function() {
this.parentElement.style.display = 'none';
console.log('Close Button. Element ' + this.parentElement.id + ' dismissed');
return false;
};
i++;
}
});
</script>
<script src="../js/live.js"></script>
......
......@@ -71,26 +71,20 @@
}
</style>
<script>// Generated by CoffeeScript 2.5.1
(function() {
document.addEventListener('DOMContentLoaded', function(event) {
var alertButtons, i;
alertButtons = document.getElementsByClassName('dismissable');
i = 0;
while (i < alertButtons.length) {
alertButtons[i].onclick = function() {
this.parentElement.style.display = 'none';
console.log('Close Button. Element ' + this.parentElement.id + ' dismissed');
return false;
};
i++;
}
});
// ---
// generated by js2coffee 2.2.0
}).call(this);
<script>// Generated by CoffeeScript 1.12.7
document.addEventListener('DOMContentLoaded', function(event) {
var alertButtons, i;
alertButtons = document.getElementsByClassName('dismissable');
i = 0;
while (i < alertButtons.length) {
alertButtons[i].onclick = function() {
this.parentElement.style.display = 'none';
console.log('Close Button. Element ' + this.parentElement.id + ' dismissed');
return false;
};
i++;
}
});
</script>
<script src="../js/live.js"></script>
......
// Generated by CoffeeScript 2.5.1
(function() {
document.addEventListener('DOMContentLoaded', function(event) {
var alertButtons, i;
alertButtons = document.getElementsByClassName('dismissable');
i = 0;
while (i < alertButtons.length) {
alertButtons[i].onclick = function() {
this.parentElement.style.display = 'none';
console.log('Close Button. Element ' + this.parentElement.id + ' dismissed');
return false;
};
i++;
}
});
// ---
// generated by js2coffee 2.2.0
}).call(this);
// Generated by CoffeeScript 1.12.7
document.addEventListener('DOMContentLoaded', function(event) {
var alertButtons, i;
alertButtons = document.getElementsByClassName('dismissable');
i = 0;
while (i < alertButtons.length) {
alertButtons[i].onclick = function() {
this.parentElement.style.display = 'none';
console.log('Close Button. Element ' + this.parentElement.id + ' dismissed');
return false;
};
i++;
}
});
......@@ -7,7 +7,7 @@ html(lang="en")
style
include:stylus ../css/style.styl
script
include:coffee-script ../js/script.coffee
include:coffee-script(bare=true) ../js/script.coffee
script(src='../js/live.js')
body
......
.container:after,
.container:before,
.panel:after,
.panel:before {
content: "";
display: table;
clear: both;
}
.container,
.panel {
padding: 0.01em 24px;
margin-top: 16px;
margin-bottom: 16px;
}
.display-container {
position: relative;
}
.red {
color: #fff !important;
background-color: #f44336 !important;
}
.yellow {
color: #000 !important;
background-color: #ffeb3b !important;
}
.green {
color: #fff !important;
background-color: #4caf50 !important;
}
.blue {
color: #fff !important;
background-color: #2196f3 !important;
}
.button {
border: none;
display: inline-block;
padding: 8px 16px;
vertical-align: middle;
overflow: hidden;
text-decoration: none;
color: inherit;
background-color: transparent;
text-align: center;
cursor: pointer;
white-space: nowrap;
}
.button {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.button:hover {
color: #000 !important;
background-color: #ccc !important;
}
.large {
font-size: 18px !important;
}
.display-topright {
position: absolute;
right: 0;
top: 0;
}
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./css/style.css":
/*!***********************!*\
!*** ./css/style.css ***!
\***********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("var api = __webpack_require__(/*! ../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\");\n var content = __webpack_require__(/*! !../node_modules/css-loader/dist/cjs.js!./style.css */ \"./node_modules/css-loader/dist/cjs.js!./css/style.css\");\n\n content = content.__esModule ? content.default : content;\n\n if (typeof content === 'string') {\n content = [[module.i, content, '']];\n }\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nmodule.exports = content.locals || {};\n\n//# sourceURL=webpack:///./css/style.css?");
/***/ }),
/***/ "./js/script.js":
/*!**********************!*\
!*** ./js/script.js ***!
\**********************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("(function() {\n document.addEventListener('DOMContentLoaded', function(event) {\n var alertButtons, i;\n alertButtons = document.getElementsByClassName('dismissable');\n i = 0;\n while (i < alertButtons.length) {\n alertButtons[i].onclick = function() {\n this.parentElement.style.display = 'none';\n console.log('Close Button. Element ' + this.parentElement.id + ' dismissed');\n return false;\n };\n i++;\n }\n });\n\n // ---\n// generated by js2coffee 2.2.0\n\n}).call(this);\n\n\n//# sourceURL=webpack:///./js/script.js?");
/***/ }),
/***/ "./node_modules/css-loader/dist/cjs.js!./css/style.css":
/*!*************************************************************!*\
!*** ./node_modules/css-loader/dist/cjs.js!./css/style.css ***!
\*************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".container:after,\\n.container:before,\\n.panel:after,\\n.panel:before {\\n content: \\\"\\\";\\n display: table;\\n clear: both;\\n}\\n.container,\\n.panel {\\n padding: 0.01em 24px;\\n margin-top: 16px;\\n margin-bottom: 16px;\\n}\\n.display-container {\\n position: relative;\\n}\\n.red {\\n color: #fff !important;\\n background-color: #f44336 !important;\\n}\\n.yellow {\\n color: #000 !important;\\n background-color: #ffeb3b !important;\\n}\\n.green {\\n color: #fff !important;\\n background-color: #4caf50 !important;\\n}\\n.blue {\\n color: #fff !important;\\n background-color: #2196f3 !important;\\n}\\n.button {\\n border: none;\\n display: inline-block;\\n padding: 8px 16px;\\n vertical-align: middle;\\n overflow: hidden;\\n text-decoration: none;\\n color: inherit;\\n background-color: transparent;\\n text-align: center;\\n cursor: pointer;\\n white-space: nowrap;\\n}\\n.button {\\n -webkit-touch-callout: none;\\n -webkit-user-select: none;\\n -khtml-user-select: none;\\n -moz-user-select: none;\\n -ms-user-select: none;\\n user-select: none;\\n}\\n.button:hover {\\n color: #000 !important;\\n background-color: #ccc !important;\\n}\\n.large {\\n font-size: 18px !important;\\n}\\n.display-topright {\\n position: absolute;\\n right: 0;\\n top: 0;\\n}\\n\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./css/style.css?./node_modules/css-loader/dist/cjs.js");
/***/ }),
/***/ "./node_modules/css-loader/dist/runtime/api.js":
/*!*****************************************************!*\
!*** ./node_modules/css-loader/dist/runtime/api.js ***!
\*****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\n// eslint-disable-next-line func-names\nmodule.exports = function (useSourceMap) {\n var list = []; // return the list of modules as css string\n\n list.toString = function toString() {\n return this.map(function (item) {\n var content = cssWithMappingToString(item, useSourceMap);\n\n if (item[2]) {\n return \"@media \".concat(item[2], \" {\").concat(content, \"}\");\n }\n\n return content;\n }).join('');\n }; // import a list of modules into the list\n // eslint-disable-next-line func-names\n\n\n list.i = function (modules, mediaQuery, dedupe) {\n if (typeof modules === 'string') {\n // eslint-disable-next-line no-param-reassign\n modules = [[null, modules, '']];\n }\n\n var alreadyImportedModules = {};\n\n if (dedupe) {\n for (var i = 0; i < this.length; i++) {\n // eslint-disable-next-line prefer-destructuring\n var id = this[i][0];\n\n if (id != null) {\n alreadyImportedModules[id] = true;\n }\n }\n }\n\n for (var _i = 0; _i < modules.length; _i++) {\n var item = [].concat(modules[_i]);\n\n if (dedupe && alreadyImportedModules[item[0]]) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n if (mediaQuery) {\n if (!item[2]) {\n item[2] = mediaQuery;\n } else {\n item[2] = \"\".concat(mediaQuery, \" and \").concat(item[2]);\n }\n }\n\n list.push(item);\n }\n };\n\n return list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n var content = item[1] || ''; // eslint-disable-next-line prefer-destructuring\n\n var cssMapping = item[3];\n\n if (!cssMapping) {\n return content;\n }\n\n if (useSourceMap && typeof btoa === 'function') {\n var sourceMapping = toComment(cssMapping);\n var sourceURLs = cssMapping.sources.map(function (source) {\n return \"/*# sourceURL=\".concat(cssMapping.sourceRoot || '').concat(source, \" */\");\n });\n return [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n }\n\n return [content].join('\\n');\n} // Adapted from convert-source-map (MIT)\n\n\nfunction toComment(sourceMap) {\n // eslint-disable-next-line no-undef\n var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n var data = \"sourceMappingURL=data:application/json;charset=utf-8;base64,\".concat(base64);\n return \"/*# \".concat(data, \" */\");\n}\n\n//# sourceURL=webpack:///./node_modules/css-loader/dist/runtime/api.js?");
/***/ }),
/***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js":
/*!****************************************************************************!*\
!*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***!
\****************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar isOldIE = function isOldIE() {\n var memo;\n return function memorize() {\n if (typeof memo === 'undefined') {\n // Test for IE <= 9 as proposed by Browserhacks\n // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\n // Tests for existence of standard globals is to allow style-loader\n // to operate correctly into non-standard environments\n // @see https://github.com/webpack-contrib/style-loader/issues/177\n memo = Boolean(window && document && document.all && !window.atob);\n }\n\n return memo;\n };\n}();\n\nvar getTarget = function getTarget() {\n var memo = {};\n return function memorize(target) {\n if (typeof memo[target] === 'undefined') {\n var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself\n\n if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n try {\n // This will throw an exception if access to iframe is blocked\n // due to cross-origin restrictions\n styleTarget = styleTarget.contentDocument.head;\n } catch (e) {\n // istanbul ignore next\n styleTarget = null;\n }\n }\n\n memo[target] = styleTarget;\n }\n\n return memo[target];\n };\n}();\n\nvar stylesInDom = [];\n\nfunction getIndexByIdentifier(identifier) {\n var result = -1;\n\n for (var i = 0; i < stylesInDom.length; i++) {\n if (stylesInDom[i].identifier === identifier) {\n result = i;\n break;\n }\n }\n\n return result;\n}\n\nfunction modulesToDom(list, options) {\n var idCountMap = {};\n var identifiers = [];\n\n for (var i = 0; i < list.length; i++) {\n var item = list[i];\n var id = options.base ? item[0] + options.base : item[0];\n var count = idCountMap[id] || 0;\n var identifier = \"\".concat(id, \" \").concat(count);\n idCountMap[id] = count + 1;\n var index = getIndexByIdentifier(identifier);\n var obj = {\n css: item[1],\n media: item[2],\n sourceMap: item[3]\n };\n\n if (index !== -1) {\n stylesInDom[index].references++;\n stylesInDom[index].updater(obj);\n } else {\n stylesInDom.push({\n identifier: identifier,\n updater: addStyle(obj, options),\n references: 1\n });\n }\n\n identifiers.push(identifier);\n }\n\n return identifiers;\n}\n\nfunction insertStyleElement(options) {\n var style = document.createElement('style');\n var attributes = options.attributes || {};\n\n if (typeof attributes.nonce === 'undefined') {\n var nonce = true ? __webpack_require__.nc : undefined;\n\n if (nonce) {\n attributes.nonce = nonce;\n }\n }\n\n Object.keys(attributes).forEach(function (key) {\n style.setAttribute(key, attributes[key]);\n });\n\n if (typeof options.insert === 'function') {\n options.insert(style);\n } else {\n var target = getTarget(options.insert || 'head');\n\n if (!target) {\n throw new Error(\"Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.\");\n }\n\n target.appendChild(style);\n }\n\n return style;\n}\n\nfunction removeStyleElement(style) {\n // istanbul ignore if\n if (style.parentNode === null) {\n return false;\n }\n\n style.parentNode.removeChild(style);\n}\n/* istanbul ignore next */\n\n\nvar replaceText = function replaceText() {\n var textStore = [];\n return function replace(index, replacement) {\n textStore[index] = replacement;\n return textStore.filter(Boolean).join('\\n');\n };\n}();\n\nfunction applyToSingletonTag(style, index, remove, obj) {\n var css = remove ? '' : obj.media ? \"@media \".concat(obj.media, \" {\").concat(obj.css, \"}\") : obj.css; // For old IE\n\n /* istanbul ignore if */\n\n if (style.styleSheet) {\n style.styleSheet.cssText = replaceText(index, css);\n } else {\n var cssNode = document.createTextNode(css);\n var childNodes = style.childNodes;\n\n if (childNodes[index]) {\n style.removeChild(childNodes[index]);\n }\n\n if (childNodes.length) {\n style.insertBefore(cssNode, childNodes[index]);\n } else {\n style.appendChild(cssNode);\n }\n }\n}\n\nfunction applyToTag(style, options, obj) {\n var css = obj.css;\n var media = obj.media;\n var sourceMap = obj.sourceMap;\n\n if (media) {\n style.setAttribute('media', media);\n } else {\n style.removeAttribute('media');\n }\n\n if (sourceMap && btoa) {\n css += \"\\n/*# sourceMappingURL=data:application/json;base64,\".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), \" */\");\n } // For old IE\n\n /* istanbul ignore if */\n\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n while (style.firstChild) {\n style.removeChild(style.firstChild);\n }\n\n style.appendChild(document.createTextNode(css));\n }\n}\n\nvar singleton = null;\nvar singletonCounter = 0;\n\nfunction addStyle(obj, options) {\n var style;\n var update;\n var remove;\n\n if (options.singleton) {\n var styleIndex = singletonCounter++;\n style = singleton || (singleton = insertStyleElement(options));\n update = applyToSingletonTag.bind(null, style, styleIndex, false);\n remove = applyToSingletonTag.bind(null, style, styleIndex, true);\n } else {\n style = insertStyleElement(options);\n update = applyToTag.bind(null, style, options);\n\n remove = function remove() {\n removeStyleElement(style);\n };\n }\n\n update(obj);\n return function updateStyle(newObj) {\n if (newObj) {\n if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) {\n return;\n }\n\n update(obj = newObj);\n } else {\n remove();\n }\n };\n}\n\nmodule.exports = function (list, options) {\n options = options || {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of <style>\n // tags it will allow on a page\n\n if (!options.singleton && typeof options.singleton !== 'boolean') {\n options.singleton = isOldIE();\n }\n\n list = list || [];\n var lastIdentifiers = modulesToDom(list, options);\n return function update(newList) {\n newList = newList || [];\n\n if (Object.prototype.toString.call(newList) !== '[object Array]') {\n return;\n }\n\n for (var i = 0; i < lastIdentifiers.length; i++) {\n var identifier = lastIdentifiers[i];\n var index = getIndexByIdentifier(identifier);\n stylesInDom[index].references--;\n }\n\n var newLastIdentifiers = modulesToDom(newList, options);\n\n for (var _i = 0; _i < lastIdentifiers.length; _i++) {\n var _identifier = lastIdentifiers[_i];\n\n var _index = getIndexByIdentifier(_identifier);\n\n if (stylesInDom[_index].references === 0) {\n stylesInDom[_index].updater();\n\n stylesInDom.splice(_index, 1);\n }\n }\n\n lastIdentifiers = newLastIdentifiers;\n };\n};\n\n//# sourceURL=webpack:///./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js?");
/***/ }),
/***/ 0:
/*!********************************************!*\
!*** multi ./js/script.js ./css/style.css ***!
\********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("__webpack_require__(/*! ./js/script.js */\"./js/script.js\");\nmodule.exports = __webpack_require__(/*! ./css/style.css */\"./css/style.css\");\n\n\n//# sourceURL=webpack:///multi_./js/script.js_./css/style.css?");
/***/ })
/******/ });
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example Webpack</title>
<script src="./bundle.js"></script>
<script src="../js/live.js"></script>
</head>
<body>
<div class="container">
<h2>Relationship Alerts</h2>
<p>To close the alerts, click on the X in the upper right corner:</p>
<div class="panel red display-container" id="red-danger"><span class="dismissable button large display-topright">&times;</span>
<p><strong>Danger!</strong>: Red light indicates door a secured.</p>
</div>
<div class="panel yellow display-container" id="yellow-warning"><span class="dismissable button large display-topright">&times;</span>
<p><strong>Warning!</strong>: Yellow light indicates that something could go wrong.</p>
</div>
<div class="panel green display-container" id="green-success"><span class="dismissable button large display-topright">&times;</span>
<p><strong>Success!</strong>: Green light indicates on schedule, on budget, all good.</p>
</div>
<div class="panel blue display-container" id="blue-info"><span class="dismissable button large display-topright">&times;</span>
<p><strong>Info!</strong>: Blue light indicates that you are in electronics mode.</p>
</div>
</div>
</body>
</html>
/*
Live.js - One script closer to Designing in the Browser
Written for Handcraft.com by Martin Kool (@mrtnkl).
Version 4.
Recent change: Made stylesheet and mimetype checks case insensitive.
http://livejs.com
http://livejs.com/license (MIT)
@livejs
Include live.js#css to monitor css changes only.
Include live.js#js to monitor js changes only.
Include live.js#html to monitor html changes only.
Mix and match to monitor a preferred combination such as live.js#html,css
By default, just include live.js to monitor all css, js and html changes.
Live.js can also be loaded as a bookmarklet. It is best to only use it for CSS then,
as a page reload due to a change in html or css would not re-include the bookmarklet.
To monitor CSS and be notified that it has loaded, include it as: live.js#css,notify
*/
(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 = {
// performs a cycle per interval
heartbeat: function () {
if (document.body) {
// make sure all resources are loaded on first activation
if (!loaded) Live.loadresources();
Live.checkForChanges();
}
setTimeout(Live.heartbeat, interval);
},
// loads all local css and js resources upon first activation
loadresources: function () {
// helper method to assert if a given url is local
function isLocal(url) {
var loc = document.location,
reg = new RegExp("^\\.|^\/(?!\/)|^[\\w]((?!://).)*$|" + loc.protocol + "//" + loc.host);
return url.match(reg);
}
// gather all resources
var scripts = document.getElementsByTagName("script"),
links = document.getElementsByTagName("link"),
uris = [];
// track local js urls
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);
// track local css urls
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;
}
}
// initialize the resources info
for (var i = 0; i < uris.length; i++) {
var url = uris[i];
Live.getHead(url, function (url, info) {
resources[url] = info;
});
}
// add rule for morphing between old and new css files
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));
// yep
loaded = true;
},
// check all tracking resources for changes
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) {
// do verification based on the header type
var oldValue = oldInfo[header],
newValue = newInfo[header],
contentType = newInfo["Content-Type"];
switch (header.toLowerCase()) {
case "etag":
if (!newValue) break;
// fall through to default
default:
hasChanged = oldValue != newValue;
break;
}
// if changed, act
if (hasChanged) {
Live.refreshResource(url, contentType);
break;
}
}
});
}
},
// act upon a changed url of certain content type
refreshResource: function (url, type) {
switch (type.toLowerCase()) {
// css files can be reloaded dynamically by replacing the link element
case "text/css":
var link = currentLinkElements[url],