| /* 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); |
| })(); |