249 lines
7 KiB
JavaScript
249 lines
7 KiB
JavaScript
/* global _ */
|
|
(function () {
|
|
'use strict'
|
|
|
|
/* jshint ignore:start */
|
|
// Underscore's Template Module
|
|
// Courtesy of underscorejs.org
|
|
var _ = (function (_) {
|
|
_.defaults = function (object) {
|
|
if (!object) {
|
|
return object
|
|
}
|
|
for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
|
|
var iterable = arguments[argsIndex]
|
|
if (iterable) {
|
|
for (var key in iterable) {
|
|
if (object[key] == null) {
|
|
object[key] = iterable[key]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return object
|
|
}
|
|
|
|
// By default, Underscore uses ERB-style template delimiters, change the
|
|
// following template settings to use alternative delimiters.
|
|
_.templateSettings = {
|
|
evaluate : /<%([\s\S]+?)%>/g,
|
|
interpolate : /<%=([\s\S]+?)%>/g,
|
|
escape : /<%-([\s\S]+?)%>/g
|
|
}
|
|
|
|
// When customizing `templateSettings`, if you don't want to define an
|
|
// interpolation, evaluation or escaping regex, we need one that is
|
|
// guaranteed not to match.
|
|
var noMatch = /(.)^/
|
|
|
|
// Certain characters need to be escaped so that they can be put into a
|
|
// string literal.
|
|
var escapes = {
|
|
"'": "'",
|
|
"\\": "\\",
|
|
"\r": "r",
|
|
"\n": "n",
|
|
"\t": "t",
|
|
"\u2028": "u2028",
|
|
"\u2029": "u2029"
|
|
}
|
|
|
|
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g
|
|
|
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
|
// and correctly escapes quotes within interpolated code.
|
|
_.template = function (text, data, settings) {
|
|
var render
|
|
settings = _.defaults({}, settings, _.templateSettings)
|
|
|
|
// Combine delimiters into one regular expression via alternation.
|
|
var matcher = new RegExp([
|
|
(settings.escape || noMatch).source,
|
|
(settings.interpolate || noMatch).source,
|
|
(settings.evaluate || noMatch).source
|
|
].join("|") + "|$", "g")
|
|
|
|
// Compile the template source, escaping string literals appropriately.
|
|
var index = 0
|
|
var source = "__p+='"
|
|
text.replace(matcher, function (match, escape, interpolate, evaluate, offset) {
|
|
source += text.slice(index, offset)
|
|
.replace(escaper, function (match) { return "\\" + escapes[match] })
|
|
|
|
if (escape) {
|
|
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"
|
|
}
|
|
if (interpolate) {
|
|
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"
|
|
}
|
|
if (evaluate) {
|
|
source += "';\n" + evaluate + "\n__p+='"
|
|
}
|
|
index = offset + match.length
|
|
return match
|
|
})
|
|
source += "';\n"
|
|
|
|
// If a variable is not specified, place data values in local scope.
|
|
if (!settings.variable) source = "with(obj||{}){\n" + source + '}\n'
|
|
|
|
source = "var __t,__p='',__j=Array.prototype.join," +
|
|
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
|
source + "return __p;\n"
|
|
|
|
try {
|
|
render = new Function(settings.variable || "obj", "_", source)
|
|
} catch (e) {
|
|
e.source = source
|
|
throw e
|
|
}
|
|
|
|
if (data) return render(data, _)
|
|
var template = function (data) {
|
|
return render.call(this, data, _)
|
|
}
|
|
|
|
// Provide the compiled function source as a convenience for precompilation.
|
|
template.source = "function(" + (settings.variable || "obj") + "){\n" + source + '}'
|
|
|
|
return template
|
|
}
|
|
|
|
return _
|
|
})({})
|
|
|
|
if (location.hostname === "todomvc.com") {
|
|
(function (i, s, o, g, r, a, m){ i["GoogleAnalyticsObject"] = r;i[r] = i[r]|| function (){
|
|
(i[r].q = i[r].q || []).push(arguments) }, i[r].l = 1 * new Date();a = s.createElement(o),
|
|
m = s.getElementsByTagName(o)[0];a.async = 1;a.src = g;m.parentNode.insertBefore(a, m)
|
|
})(window, document,"script","https://www.google-analytics.com/analytics.js","ga")
|
|
ga("create", "UA-31081062-1", "auto")
|
|
ga("send", "pageview")
|
|
}
|
|
/* jshint ignore:end */
|
|
|
|
function redirect() {
|
|
if (location.hostname === "tastejs.github.io") {
|
|
location.href = location.href.replace("tastejs.github.io/todomvc", "todomvc.com")
|
|
}
|
|
}
|
|
|
|
function findRoot() {
|
|
var base = location.href.indexOf("examples/")
|
|
return location.href.substr(0, base)
|
|
}
|
|
|
|
function getFile(file, callback) {
|
|
if (!location.host) {
|
|
return console.info("Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.")
|
|
}
|
|
|
|
var xhr = new XMLHttpRequest()
|
|
|
|
xhr.open("GET", findRoot() + file, true)
|
|
xhr.send()
|
|
|
|
xhr.onload = function () {
|
|
if (xhr.status === 200 && callback) {
|
|
callback(xhr.responseText)
|
|
}
|
|
}
|
|
}
|
|
|
|
function Learn(learnJSON, config) {
|
|
if (!(this instanceof Learn)) {
|
|
return new Learn(learnJSON, config)
|
|
}
|
|
|
|
var template, framework
|
|
|
|
if (typeof learnJSON !== "object") {
|
|
try {
|
|
learnJSON = JSON.parse(learnJSON)
|
|
} catch (e) {
|
|
return
|
|
}
|
|
}
|
|
|
|
if (config) {
|
|
template = config.template
|
|
framework = config.framework
|
|
}
|
|
|
|
if (!template && learnJSON.templates) {
|
|
template = learnJSON.templates.todomvc
|
|
}
|
|
|
|
if (!framework && document.querySelector("[data-framework]")) {
|
|
framework = document.querySelector("[data-framework]").dataset.framework
|
|
}
|
|
|
|
this.template = template
|
|
|
|
if (learnJSON.backend) {
|
|
this.frameworkJSON = learnJSON.backend
|
|
this.frameworkJSON.issueLabel = framework
|
|
this.append({
|
|
backend: true
|
|
})
|
|
} else if (learnJSON[framework]) {
|
|
this.frameworkJSON = learnJSON[framework]
|
|
this.frameworkJSON.issueLabel = framework
|
|
this.append()
|
|
}
|
|
|
|
this.fetchIssueCount()
|
|
}
|
|
|
|
Learn.prototype.append = function (opts) {
|
|
var aside = document.createElement("aside")
|
|
aside.innerHTML = _.template(this.template, this.frameworkJSON)
|
|
aside.className = 'learn'
|
|
|
|
if (opts && opts.backend) {
|
|
// Remove demo link
|
|
var sourceLinks = aside.querySelector(".source-links")
|
|
var heading = sourceLinks.firstElementChild
|
|
var sourceLink = sourceLinks.lastElementChild
|
|
// Correct link path
|
|
var href = sourceLink.getAttribute("href")
|
|
sourceLink.setAttribute("href", href.substr(href.lastIndexOf("http")))
|
|
sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML
|
|
} else {
|
|
// Localize demo links
|
|
var demoLinks = aside.querySelectorAll(".demo-link")
|
|
Array.prototype.forEach.call(demoLinks, function (demoLink) {
|
|
if (demoLink.getAttribute("href").substr(0, 4) !== "http") {
|
|
demoLink.setAttribute("href", findRoot() + demoLink.getAttribute("href"))
|
|
}
|
|
})
|
|
}
|
|
|
|
document.body.className = (document.body.className + " learn-bar").trim()
|
|
document.body.insertAdjacentHTML("afterBegin", aside.outerHTML)
|
|
}
|
|
|
|
Learn.prototype.fetchIssueCount = function () {
|
|
var issueLink = document.getElementById("issue-count-link")
|
|
if (issueLink) {
|
|
var url = issueLink.href.replace("https://github.com", "https://api.github.com/repos")
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open("GET", url, true)
|
|
xhr.onload = function (e) {
|
|
var parsedResponse = JSON.parse(e.target.responseText)
|
|
if (parsedResponse instanceof Array) {
|
|
var count = parsedResponse.length
|
|
if (count !== 0) {
|
|
issueLink.innerHTML = "This app has " + count + ' open issues'
|
|
document.getElementById("issue-count").style.display = 'inline'
|
|
}
|
|
}
|
|
}
|
|
xhr.send()
|
|
}
|
|
}
|
|
|
|
redirect()
|
|
getFile("learn.json", Learn)
|
|
})()
|