├── app ├── booktree.png ├── templates │ └── description.html ├── scripts │ ├── Utils.js │ ├── main.js │ └── render.js ├── styles │ ├── layout.css │ ├── mifa.min.css │ └── tooltipster.css ├── data │ ├── lang.json │ ├── cd.json │ ├── code.json │ ├── arch.json │ ├── ml.json │ └── frontend.json ├── lib │ ├── FileSaver.min.js │ ├── json.js │ ├── text.js │ ├── lettuce.js │ ├── underscore-min.js │ ├── jquery.tooltipster.min.js │ └── underscore-min.map └── assets │ ├── lang.svg │ ├── cd.svg │ ├── code.svg │ ├── frontend.svg │ └── ml.svg ├── screenshots ├── cd.jpg ├── cd.png ├── dsl.jpg ├── dsl.png ├── ml.jpg ├── ml.png ├── arch.jpg ├── arch.png ├── code.jpg ├── code.png ├── frontend.jpg └── frontend.png ├── .gitignore ├── .travis.yml ├── bower.json ├── .jshintrc ├── .editorconfig ├── package.json ├── gulpfile.js ├── index.html ├── README.md └── LICENSE /app/booktree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/app/booktree.png -------------------------------------------------------------------------------- /screenshots/cd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/cd.jpg -------------------------------------------------------------------------------- /screenshots/cd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/cd.png -------------------------------------------------------------------------------- /screenshots/dsl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/dsl.jpg -------------------------------------------------------------------------------- /screenshots/dsl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/dsl.png -------------------------------------------------------------------------------- /screenshots/ml.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/ml.jpg -------------------------------------------------------------------------------- /screenshots/ml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/ml.png -------------------------------------------------------------------------------- /screenshots/arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/arch.jpg -------------------------------------------------------------------------------- /screenshots/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/arch.png -------------------------------------------------------------------------------- /screenshots/code.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/code.jpg -------------------------------------------------------------------------------- /screenshots/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/code.png -------------------------------------------------------------------------------- /screenshots/frontend.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/frontend.jpg -------------------------------------------------------------------------------- /screenshots/frontend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/booktree/gh-pages/screenshots/frontend.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | .sass-cache 5 | bower_components 6 | test/bower_components 7 | .idea 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | notifications: 6 | email: false 7 | 8 | branches: 9 | only: 10 | - gh-pages 11 | -------------------------------------------------------------------------------- /app/templates/description.html: -------------------------------------------------------------------------------- 1 |
2 |

{%=o.title%}

3 |

豆瓣链接: {%=o.title%}

4 |

{%=o.description%}

5 |
6 | 7 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "skillock", 3 | "private": true, 4 | "dependencies": { 5 | "jquery": "2.1.3", 6 | "d3": "3.5.5", 7 | "requirejs": "2.1.16", 8 | "knockout": "2.3.0", 9 | "dagre-d3": "~0.4.17", 10 | "lettuce": "~0.2.3" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/scripts/Utils.js: -------------------------------------------------------------------------------- 1 | define(['lib/knockout'], function(ko) { 2 | 'use strict'; 3 | function getSkillById(books, id) { 4 | var result = []; 5 | ko.utils.arrayForEach(books, function (skill) { 6 | if(skill.id === id){ 7 | result = skill; 8 | } 9 | }); 10 | return result; 11 | } 12 | 13 | return { 14 | getSkillById: getSkillById 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "curly": true, 6 | "eqeqeq": true, 7 | "immed": true, 8 | "indent": 2, 9 | "latedef": true, 10 | "newcap": true, 11 | "noarg": true, 12 | "quotmark": "single", 13 | "undef": true, 14 | "unused": false, 15 | "strict": true, 16 | "jquery": true, 17 | "laxcomma": true, 18 | "scripturl": true, 19 | "predef": [ 20 | "require", 21 | "define", 22 | "escape", 23 | "console" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # we recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | [{package,bower}.json] 24 | indent_style = space 25 | indent_size = 2 26 | -------------------------------------------------------------------------------- /app/scripts/main.js: -------------------------------------------------------------------------------- 1 | require.config({ 2 | baseUrl: 'app', 3 | paths: { 4 | jquery: 'lib/jquery-2.1.3', 5 | json: 'lib/json', 6 | d3: 'lib/d3.min', 7 | 'dagre-d3': 'lib/dagre-d3.min', 8 | text: 'lib/text', 9 | lettuce: 'lib/lettuce', 10 | 'underscore': 'lib/underscore-min', 11 | 'jquery.tooltipster': 'lib/jquery.tooltipster.min' 12 | }, 13 | 'shim': { 14 | 'jquery.tooltipster': { 15 | deps: ['jquery'] 16 | }, 17 | 'dagre-d3': { 18 | deps: ['d3'] 19 | } 20 | } 21 | }); 22 | 23 | require(['lib/knockout', 'scripts/render', 24 | 'json!data/code.json', 25 | 'json!data/frontend.json', 26 | 'json!data/cd.json', 27 | 'json!data/lang.json', 28 | 'json!data/arch.json', 29 | 'json!data/ml.json' 30 | ], 31 | function (ko, render, 32 | code, 33 | frontend, 34 | cd, 35 | lang, 36 | arch, 37 | ml) { 38 | 'use strict'; 39 | 40 | render.renderPage(code, '#code'); 41 | render.renderPage(frontend, '#frontend'); 42 | render.renderPage(cd, '#cd'); 43 | render.renderPage(lang, '#lang'); 44 | render.renderPage(arch, '#arch'); 45 | render.renderPage(ml, '#ml'); 46 | }); 47 | -------------------------------------------------------------------------------- /app/styles/layout.css: -------------------------------------------------------------------------------- 1 | section { 2 | margin-bottom: 3em; 3 | } 4 | 5 | #tree { 6 | width: 1200px; 7 | margin: 0 auto; 8 | } 9 | 10 | svg { 11 | width: 1440px; 12 | overflow: hidden; 13 | margin: auto 0; 14 | } 15 | 16 | .node rect { 17 | stroke: #333; 18 | fill: #fff; 19 | } 20 | 21 | g.node rect { 22 | stroke: #bdc3c7; 23 | stroke-width: 2.5px; 24 | cursor: pointer; 25 | } 26 | 27 | g.node rect.inner { 28 | fill: white; 29 | } 30 | 31 | g.node rect.outer { 32 | position: absolute; 33 | display: none; 34 | stroke-dasharray: 4px; 35 | stroke-opacity: 0.5; 36 | fill: transparent; 37 | } 38 | 39 | g.selected rect.outer { 40 | display: inline; 41 | } 42 | 43 | rect.selection { 44 | stroke: gray; 45 | stroke-dasharray: 4px; 46 | stroke-opacity: 0.5; 47 | fill: transparent; 48 | } 49 | 50 | .edgePath path { 51 | stroke: gray; 52 | fill: gray; 53 | stroke-width: 1.5px; 54 | } 55 | 56 | .node text { 57 | pointer-events: none; 58 | fill: #34495e; 59 | } 60 | 61 | /* disable text selection */ 62 | svg *::selection { 63 | background: transparent; 64 | } 65 | 66 | svg *::-moz-selection { 67 | background: transparent; 68 | } 69 | 70 | svg *::-webkit-selection { 71 | background: transparent; 72 | } 73 | 74 | path { 75 | color: #ddd; 76 | fill: #ddd; 77 | } 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "engines": { 4 | "node": ">=0.10.0" 5 | }, 6 | "scripts": { 7 | "test": "mocha --reporter spec" 8 | }, 9 | "devDependencies": { 10 | "chai": "~1.8.0", 11 | "connect": "^3.0.1", 12 | "connect-livereload": "^0.5.0", 13 | "del": "^0.1.0", 14 | "expect.js": ">= 0.3.1", 15 | "gulp": "^3.6.0", 16 | "gulp-autoprefixer": "^1.0.1", 17 | "gulp-cache": "^0.2.2", 18 | "gulp-csso": "^0.2.6", 19 | "gulp-filter": "^1.0.2", 20 | "gulp-flatten": "^0.0.4", 21 | "gulp-if": "^1.2.1", 22 | "gulp-jshint": "^1.5.3", 23 | "gulp-livereload": "^2.0.0", 24 | "gulp-load-plugins": "^0.7.1", 25 | "gulp-mocha": "2.0.0", 26 | "gulp-plumber": "^0.6.3", 27 | "gulp-replace": "^0.4.0", 28 | "gulp-size": "^1.1.0", 29 | "gulp-uglify": "^1.0.1", 30 | "gulp-useref": "^1.0.2", 31 | "istanbul": "^0.3.0", 32 | "jsdom": "3.1.2", 33 | "jshint-stylish": "^1.0.0", 34 | "json-concat": "0.0.0-alpha.1.0", 35 | "lazypipe": "^0.2.1", 36 | "main-bower-files": "^2.1.0", 37 | "mocha": "2.1.0", 38 | "mocha-jsdom": "^0.2.1", 39 | "mocha-lcov-reporter": "^0.0.1", 40 | "opn": "^1.0.0", 41 | "requirejs": "2.1.16", 42 | "serve-index": "^1.1.4", 43 | "serve-static": "^1.4.0", 44 | "should": ">= 3.2.0", 45 | "wiredep": "^2.0.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/data/lang.json: -------------------------------------------------------------------------------- 1 | { 2 | "books": [ 3 | { 4 | "id": 1, 5 | "description": "龙书!龙书!龙书!", 6 | "title": "《编译原理》", 7 | "douban": "http://book.douban.com/subject/3296317/" 8 | }, 9 | { 10 | "id": 3, 11 | "description": "旨在传授开发语言应用(工具)的经验和理念,帮助读者构建自己的语言应用。", 12 | "title": "《编程语言实现模式》", 13 | "depends": [ 14 | 1 15 | ], 16 | "douban": "http://book.douban.com/subject/10482195/" 17 | }, 18 | { 19 | "id": 2, 20 | "description": "书中以问答方式告诉为什么要创建某种编程语言、它在技术上如何开发、如何教授和学习,以及它如何顺应时代发展等。你会发现构建成功编程语言所需的思想和步骤,它广受欢迎的原因,以及如何处理程序员常见的问题。", 21 | "title": "《编程之魂》", 22 | "douban": "http://book.douban.com/subject/4719230/" 23 | }, 24 | { 25 | "id": 4, 26 | "description": "本书堪称动态语言设计模式。", 27 | "title": "《Ruby元编程》", 28 | "douban": "http://book.douban.com/subject/7056800/" 29 | }, 30 | { 31 | "id": 5, 32 | "description": "不仅介绍如何使用DSL解决问题,还会使用Ruby、Groovy、Scala、Clojure等现代语言阐述DSL的设计与实现,针对这些语言所代表的不同编程范式深入讨论其在DSL设计上的优劣。", 33 | "title": "《领域专用语言实战》", 34 | "depends": [ 35 | 3, 4, 2 36 | ], 37 | "douban": "http://book.douban.com/subject/25741352/" 38 | }, 39 | { 40 | "id": 6, 41 | "description": "全面详尽地讲解了各种DSL及其构造方式,揭示了与编程语言无关的通用原则和模式,阐释了如何通过DSL有效提高开发人员的生产力以及增进与领域专家的有效沟通,能为开发人员选择和使用DSL提供有效的决策依据和指导方法。", 42 | "title": "《领域特定语言》", 43 | "depends": [ 44 | 5 45 | ], 46 | "douban": "http://book.douban.com/subject/21964984/" 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* jshint node:true */ 2 | 'use strict'; 3 | var gulp = require('gulp'); 4 | var $ = require('gulp-load-plugins')(); 5 | var mocha = require('gulp-mocha'); 6 | 7 | gulp.task('contact', function () { 8 | var jsonConcat = require("json-concat"); 9 | 10 | jsonConcat({ 11 | src: ["data/0.json", "data/1-html.json"], 12 | dest: "./data/data.json" 13 | }, function (json) { 14 | console.log(json); 15 | }); 16 | }); 17 | 18 | gulp.task('jshint', function () { 19 | return gulp.src('app/scripts/**/*.js') 20 | .pipe($.jshint()) 21 | .pipe($.jshint.reporter('jshint-stylish')) 22 | .pipe($.jshint.reporter('fail')); 23 | }); 24 | 25 | gulp.task('connect', function () { 26 | var serveStatic = require('serve-static'); 27 | var serveIndex = require('serve-index'); 28 | var app = require('connect')() 29 | .use(require('connect-livereload')({port: 35729})) 30 | .use(serveStatic('./')) 31 | .use(serveIndex('./')); 32 | 33 | require('http').createServer(app) 34 | .listen(9000) 35 | .on('listening', function () { 36 | console.log('Started connect web server on http://localhost:9000'); 37 | }); 38 | }); 39 | 40 | gulp.task('serve', ['connect', 'watch'], function () { 41 | require('opn')('http://localhost:9000'); 42 | }); 43 | 44 | gulp.task('watch', ['connect'], function () { 45 | $.livereload.listen(); 46 | 47 | gulp.watch([ 48 | 'index.html', 49 | 'app/scripts/**.js', 50 | 'app/images/**/*', 51 | 'app/styles/**/*.css', 52 | 'app/templates/**.html', 53 | 'app/logo/**/*', 54 | 'data/**.json' 55 | ]).on('change', $.livereload.changed); 56 | }); 57 | 58 | gulp.task('build', ['jshint'], function () { 59 | return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true})); 60 | }); 61 | 62 | gulp.task('default', function () { 63 | gulp.start('build'); 64 | }); 65 | -------------------------------------------------------------------------------- /app/data/cd.json: -------------------------------------------------------------------------------- 1 | { 2 | "books": [ 3 | { 4 | "id": 1, 5 | "description": "讲述了在预算和时间要求下软件开发人员和项目经理如何使用敏捷开发完成项目:使用真实案例讲解如何用极限编程来设计、测试、重构和结对编程;包含了极具价值的可重用的C++和Java源代码;还重点讲述了如何使用UML和设计模式解决面向客户系统的问题。", 6 | "title": "《敏捷软件开发:原则、模式与实践》", 7 | "depends": [ 8 | 2 9 | ], 10 | "douban": "http://book.douban.com/subject/1140457/" 11 | }, 12 | { 13 | "id": 2, 14 | "description": "这本书讲解了代码管理工具和系统的历史和发展,然后从小型团队、中大型团队、分布式大团队、基于微服务的团队及开源团队的角度总结了代码管理的核心技术及实践经验,其中包括不同类型的团队对代码管理工具和系统的选择,以及代码管理的流程、策略和技巧,还有一些代码管理工具和系统的难点、痛点等", 15 | "title": "《代码管理核心技术及实践》", 16 | "douban": "https://book.douban.com/subject/27611269/" 17 | }, 18 | { 19 | "id": 3, 20 | "description": "以一次自评价测试开篇,从软件测试的心理学和经济学入手,探讨了代码检查、走查与评审、测试用例的设计、模块(单元)测试、系统测试、调试等主题,以及极限测试、互联网应用测试等高级主题,全面展现了作者的软件测试思想。", 21 | "title": "《软件测试的艺术》", 22 | "douban": "http://book.douban.com/subject/10549782/" 23 | }, 24 | { 25 | "id": 5, 26 | "description": "自动化测试", 27 | "title": "《Cucumber:行为驱动开发指南》", 28 | "douban": "http://book.douban.com/subject/24843412/" 29 | }, 30 | { 31 | "id": 6, 32 | "description": "测试是敏捷开发的关键组成部分。敏捷方法的广泛应用使人们开始关注如何有效测试,同时敏捷项目改变了测试人员的角色。", 33 | "title": "《敏捷软件测试》", 34 | "depends": [ 35 | 3, 5 36 | ], 37 | "douban": "http://book.douban.com/subject/5338399/" 38 | }, 39 | { 40 | "id": 7, 41 | "description": "构造系统在软件开发过程中处于核心地位,它的正确性和性能,在一定程度上决定了软件开发成果的质量和软件开发过程的效率。", 42 | "title": "《深入理解软件构造系统》", 43 | "douban": "http://book.douban.com/subject/10769838/" 44 | }, 45 | { 46 | "id": 8, 47 | "description": "旨在指导配置管理从业者如何处理日常工作中需要面对的各种复杂情况。", 48 | "title": "《配置管理最佳实践》", 49 | "douban": "http://book.douban.com/subject/25717078/" 50 | }, 51 | { 52 | "id": 10, 53 | "description": "讲述如何实现更快、更可靠、低成本的自动化软件交付,描述了如何通过增加反馈,并改进开发人员、测试人员、运维人员和项目经理之间的协作来达到这个目标。", 54 | "title": "《持续交付:发布可靠软件的系统方法》", 55 | "depends": [ 56 | 1, 6, 7, 8 57 | ], 58 | "douban": "http://book.douban.com/subject/6862062/" 59 | } 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /app/lib/FileSaver.min.js: -------------------------------------------------------------------------------- 1 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 2 | var saveAs=saveAs||function(e){"use strict";if(!("undefined"==typeof e||"undefined"!=typeof navigator&&/MSIE [1-9]\./.test(navigator.userAgent))){var t=e.document,n=function(){return e.URL||e.webkitURL||e},o=t.createElementNS("http://www.w3.org/1999/xhtml","a"),r="download"in o,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,d=/CriOS\/[\d]+/.test(navigator.userAgent),f=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",u=4e4,c=function(e){var t=function(){"string"==typeof e?n().revokeObjectURL(e):e.remove()};setTimeout(t,u)},l=function(e,t,n){t=[].concat(t);for(var o=t.length;o--;){var r=e["on"+t[o]];if("function"==typeof r)try{r.call(e,n||e)}catch(a){f(a)}}},v=function(e){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob([String.fromCharCode(65279),e],{type:e.type}):e},p=function(t,f,u){u||(t=v(t));var p,w=this,m=t.type,y=m===s,S=function(){l(w,"writestart progress write writeend".split(" "))},h=function(){if((d||y&&i)&&e.FileReader){var o=new FileReader;return o.onloadend=function(){var t=d?o.result:o.result.replace(/^data:[^;]*;/,"data:attachment/file;"),n=e.open(t,"_blank");n||(e.location.href=t),t=void 0,w.readyState=w.DONE,S()},o.readAsDataURL(t),void(w.readyState=w.INIT)}if(p||(p=n().createObjectURL(t)),y)e.location.href=p;else{var r=e.open(p,"_blank");r||(e.location.href=p)}w.readyState=w.DONE,S(),c(p)};return w.readyState=w.INIT,r?(p=n().createObjectURL(t),void setTimeout(function(){o.href=p,o.download=f,a(o),S(),c(p),w.readyState=w.DONE})):void h()},w=p.prototype,m=function(e,t,n){return new p(e,t||e.name||"download",n)};return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t,n){return t=t||e.name||"download",n||(e=v(e)),navigator.msSaveOrOpenBlob(e,t)}:(w.abort=function(){},w.readyState=w.INIT=0,w.WRITING=1,w.DONE=2,w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null,m)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this);"undefined"!=typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!=typeof define&&null!==define&&null!==define.amd&&define("FileSaver.js",function(){return saveAs}); -------------------------------------------------------------------------------- /app/data/code.json: -------------------------------------------------------------------------------- 1 | { 2 | "books": [ 3 | { 4 | "id": 1, 5 | "description": "尽管在国内,我们很少听到开发人员写测试,就更少听人们谈论TDD。虽然我不是TDD的死忠,但是我觉得TDD还是很有好处的。特别是当你的函数特别长的时候,它可以驱使你写出更短的函数——更多的函数。红->绿->重构,就是这么简单。", 6 | "title": "《测试驱动开发》", 7 | "douban": "http://book.douban.com/subject/25735501/" 8 | }, 9 | { 10 | "id": 2, 11 | "description": "红->绿->重构。如果重构之前没有测试,我相信你可能是想换个工作了。好的代码是重构出来的,而不是一开始就写出来的——除非你的代码不用于任何业务。反正,就是程序员必读,不想多说。", 12 | "title": "《重构: 改善既有代码的设计》", 13 | "depends": [ 14 | 1 15 | ], 16 | "douban": "http://book.douban.com/subject/26575459/" 17 | }, 18 | { 19 | "id": 3, 20 | "description": "GoF的《设计模式》一书很薄,所以也很抽象。第一次看《设计模式》的时候,硬着头皮看了几天,然后放弃了。。。不过,Head First系列可以将各种枯燥的设计生起起来,这是一本非常适合入门设计模式的书籍没有之一。", 21 | "title": "《Head First设计模式》", 22 | "douban": "http://book.douban.com/subject/2243615/" 23 | }, 24 | { 25 | "id": 4, 26 | "description": "比Head First更深入,但是比DP简单。作者选用了一些常用或者说用到的模式,讲述了为什么在这里适合用它。", 27 | "title": "《设计模式解析》", 28 | "depends": [ 29 | 3 30 | ], 31 | "douban": "http://book.douban.com/subject/1850191/" 32 | }, 33 | { 34 | "id": 5, 35 | "description": "纳尼!你居然不想买这本书?", 36 | "title": "《易读代码的艺术/编写可读代码的艺术》", 37 | "douban": "http://book.douban.com/subject/10773334/" 38 | }, 39 | { 40 | "id": 6, 41 | "description": "书中给了很方法与规范,遵循它们可以写出整洁的代码。但是整洁并不意味着你应该让代码简单!", 42 | "title": "《代码整洁之道》", 43 | "depends": [ 44 | 5 45 | ], 46 | "douban": "http://book.douban.com/subject/4199741/" 47 | }, 48 | { 49 | "id": 7, 50 | "description": "这本书的中文名字应该叫《重构到模式》!!!重构代码到设计模式就这么简单。", 51 | "title": "《重构与模式》", 52 | "depends": [ 53 | 2, 6 54 | ], 55 | "douban": "http://book.douban.com/subject/1917706/" 56 | }, 57 | { 58 | "id": 8, 59 | "description": "必读,并且值得多读几遍。", 60 | "title": "《设计模式》", 61 | "depends": [ 62 | 4, 7, 9 63 | ], 64 | "douban": "http://book.douban.com/subject/1052241/" 65 | }, 66 | { 67 | "id": 9, 68 | "description": "首先书名很扯!!!这本书更适合叫《设计模式要素》!这本书提取了设计模式中的一些基本元素,很具有启发性。", 69 | "title": "《元素模式》", 70 | "depends": [ 71 | 8 72 | ], 73 | "douban": "http://book.douban.com/subject/25908396/" 74 | } 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /app/data/arch.json: -------------------------------------------------------------------------------- 1 | { 2 | "books": [ 3 | { 4 | "id": 1, 5 | "description": "经典!", 6 | "title": "《企业应用架构模式》" 7 | }, 8 | { 9 | "id": 2, 10 | "description": "本书将成为与《设计模式》一样的被读者广泛认可的经典之作。《设计模式》只探讨了面向对象开发的一个抽象层级,而本书涵盖了三个:高层的架构模式、中层的设计模式,以及特定语言的成例。", 11 | "title": "《面向模式的软件架构卷1: 模式系统》", 12 | "depends": [ 13 | 1, 10 14 | ], 15 | "douban": "http://book.douban.com/subject/25741382/" 16 | }, 17 | { 18 | "id": 3, 19 | "description": "全面详尽地讲解了各种DSL及其构造方式,揭示了与编程语言无关的通用原则和模式,阐释了如何通过DSL有效提高开发人员的生产力以及增进与领域专家的有效沟通,能为开发人员选择和使用DSL提供有效的决策依据和指导方法。", 20 | "title": "《领域特定语言》", 21 | "douban": "http://book.douban.com/subject/21964984/" 22 | }, 23 | { 24 | "id": 4, 25 | "description": "分别从战略和战术层面详尽地讨论了如何实现DDD,其中包含了大量的最佳实践、设计准则和对一些问题的折中性讨论。", 26 | "title": "《实现领域驱动设计》", 27 | "depends": [ 28 | 3 29 | ], 30 | "douban": "http://book.douban.com/subject/25844633/" 31 | }, 32 | { 33 | "id": 5, 34 | "description": "全书围绕着设计和开发实践,结合若干真实的项目案例,向读者阐述如何在真实的软件开发中应用领域驱动设计。 ", 35 | "title": "《领域驱动设计》", 36 | "depends": [ 37 | 4 38 | ], 39 | "douban": "http://book.douban.com/subject/5344973/" 40 | }, 41 | { 42 | "id": 6, 43 | "description": "主要面向软件开发者群体,尤其是对敏捷开发感兴趣的程序设计人员。浮现式设计是一种敏捷技术,强调在开发过程中不断演进。", 44 | "title": "《浮现式设计:专业软件开发的演进本质》", 45 | "douban": "http://book.douban.com/subject/6757781/" 46 | }, 47 | { 48 | "id": 7, 49 | "description": "作者建议根据项目面临的风险来调整架构设计的成本,并从多个视角阐述了软件架构的建模过程和方法,包括用例模型、概念模型、域模型、设计模型和代码模型等。", 50 | "title": "《恰如其分的软件架构》", 51 | "douban": "http://book.douban.com/subject/24872314/" 52 | }, 53 | { 54 | "id": 10, 55 | "description": "书中揭示了模块化的重要性,如何实现模块化,以及如何使用OSGi实现模块化架构。", 56 | "title": "《Java应用架构设计》", 57 | "douban": "http://book.douban.com/subject/25770095/" 58 | }, 59 | { 60 | "id": 8, 61 | "description": "从全新的视角重新解读软件架构,揭示软件架构的本质,是一本强调实践、注重实效、轻量级、面向开发人员的软件架构指南。", 62 | "title": "《程序员必读之软件架构》", 63 | "depends": [ 64 | 6, 7 65 | ], 66 | "douban": "http://book.douban.com/subject/26248182/" 67 | }, 68 | { 69 | "id": 9, 70 | "description": "围绕5个主题领域来组织《架构之美》的内容:概述、企业应用、系统、最终用户应用和编程语言。", 71 | "title": "《架构之美》", 72 | "depends": [ 73 | 2, 5, 8 74 | ], 75 | "douban": "http://book.douban.com/subject/4086029/" 76 | } 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /app/lib/json.js: -------------------------------------------------------------------------------- 1 | /** @license 2 | * RequireJS plugin for loading JSON files 3 | * - depends on Text plugin and it was HEAVILY "inspired" by it as well. 4 | * Author: Miller Medeiros 5 | * Version: 0.4.0 (2014/04/10) 6 | * Released under the MIT license 7 | */ 8 | define(['text'], function(text){ 9 | 10 | var CACHE_BUST_QUERY_PARAM = 'bust', 11 | CACHE_BUST_FLAG = '!bust', 12 | jsonParse = (typeof JSON !== 'undefined' && typeof JSON.parse === 'function')? JSON.parse : function(val){ 13 | return eval('('+ val +')'); //quick and dirty 14 | }, 15 | buildMap = {}; 16 | 17 | function cacheBust(url){ 18 | url = url.replace(CACHE_BUST_FLAG, ''); 19 | url += (url.indexOf('?') < 0)? '?' : '&'; 20 | return url + CACHE_BUST_QUERY_PARAM +'='+ Math.round(2147483647 * Math.random()); 21 | } 22 | 23 | //API 24 | return { 25 | 26 | load : function(name, req, onLoad, config) { 27 | if (( config.isBuild && (config.inlineJSON === false || name.indexOf(CACHE_BUST_QUERY_PARAM +'=') !== -1)) || (req.toUrl(name).indexOf('empty:') === 0)) { 28 | //avoid inlining cache busted JSON or if inlineJSON:false 29 | //and don't inline files marked as empty! 30 | onLoad(null); 31 | } else { 32 | text.get(req.toUrl(name), function(data){ 33 | var parsed; 34 | if (config.isBuild) { 35 | buildMap[name] = data; 36 | onLoad(data); 37 | } else { 38 | try { 39 | parsed = jsonParse(data); 40 | } catch (e) { 41 | onLoad.error(e); 42 | } 43 | onLoad(parsed); 44 | } 45 | }, 46 | onLoad.error, { 47 | accept: 'application/json' 48 | } 49 | ); 50 | } 51 | }, 52 | 53 | normalize : function (name, normalize) { 54 | // used normalize to avoid caching references to a "cache busted" request 55 | if (name.indexOf(CACHE_BUST_FLAG) !== -1) { 56 | name = cacheBust(name); 57 | } 58 | // resolve any relative paths 59 | return normalize(name); 60 | }, 61 | 62 | //write method based on RequireJS official text plugin by James Burke 63 | //https://github.com/jrburke/requirejs/blob/master/text.js 64 | write : function(pluginName, moduleName, write){ 65 | if(moduleName in buildMap){ 66 | var content = buildMap[moduleName]; 67 | write('define("'+ pluginName +'!'+ moduleName +'", function(){ return '+ content +';});\n'); 68 | } 69 | } 70 | 71 | }; 72 | }); 73 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Book Tree - Developer进阶书单 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

Developer进阶书单

15 |

Github: https://github.com/phodal/booktree 16 |
17 | Weibo: @phodal

18 |

一直画/写一个推荐书单来供大家参考,无奈找不到一本合适的形式。有一天,想到了之前的技术树 https://github.com/phodal/sherlock,便开始落地了。

19 |

我深知自己的知识有限,所以写下本文以便和大家切磋交流。欢迎通过 GitHub 的Issues或者直接Pull Requests方式来分享你的经验。期待你的反馈。

20 | 21 |

基本阅读路线图:

22 | Book Tree 23 |

说明: 完成工作是一件很容易的事,如何更好地完成工作就需要更多地学习。并且我坚信每一个有技术热情的人,都希望可以看到自己写的框架可以无处不在。 24 | 25 |

《技术的本质》 - W. Brain Arthur早已看穿了一切

26 | 27 |

这是一本关于『技术是什么,它是如何进化』的书。新的技术是根据于我们当前的目的、一个可实现的原理、一种新现象而发明的。并且,新的技术都是基于之前的技术发展出来的。

28 |

So,通过研究现有技术的一些发展,我们可以预料到一些新的技术的出现。尽管新的技术并没有解决一些根本性问题,如业务,但是它是为了业务而简化现有的技术。

29 |

如何写好代码——重构与设计模式

30 | 31 | 32 | 33 |

如何写前端框架——前端读书路线图

34 | 35 |

本图已被《JavaScript 框架设计:第 2 版》收录。

36 | 37 | 38 |

机器学习读书路线

39 | 40 | 41 | 42 |

持续交付读书路线图

43 | 44 | 45 | 46 |

领域特定语言读书路线图

47 | 48 | 49 |

相关文章:

50 | 53 | 54 |

架构与模式读书路线图

55 | 56 | 57 |

相关文章:

58 | 61 | 62 |

代码大全

63 |

64 | 详细讨论了类和函数命名、变量命名、数据类型和控制结构、代码布局等编程的最基本要素,也讨论了防御式编程、表驱动法、协同构建、开发者测试、性能优化等有效开发实践,这些都服务于软件的首要技术使命:管理复杂度。 65 |

66 |

© 2015 Phodal Huang. See LICENSE.txt in this directory.

67 |
68 | 69 | 70 | -------------------------------------------------------------------------------- /app/data/ml.json: -------------------------------------------------------------------------------- 1 | { 2 | "books": [ 3 | { 4 | "id": 1, 5 | "description": "本书通过丰富的案例学习来解释Hadoop的幕后机理,阐述了Hadoop如何解决现实生活中的具体问题。", 6 | "title": "《Hadoop权威指南》", 7 | "douban": "http://book.douban.com/subject/26206050/" 8 | }, 9 | { 10 | "id": 2, 11 | "description": "适合刚刚接触Python的分析人员以及刚刚接触科学计算的Python程序员。将IPython这个交互式Shell作为你的首要开发环境。", 12 | "title": "《利用Python进行数据分析》", 13 | "douban": "http://book.douban.com/subject/25779298/" 14 | }, 15 | { 16 | "id": 3, 17 | "description": "本书是写给那些拥有一个数据集合,好奇如何探索它,并且考虑如何交流这些数据的人们的。随着我们处理越来越多的信息,需要可视化数据的人的数量增长非常迅速。", 18 | "title": "《可视化数据》", 19 | "depends": [ 20 | 1, 2 21 | ], 22 | "douban": "http://book.douban.com/subject/3661214/" 23 | }, 24 | { 25 | "id": 4, 26 | "description": "这本书帮助那些希望用数学工具解决实际问题的人们,仅有的要求可能就是懂一点概率知识和程序设计。而贝叶斯方法是一种常见的利用概率学知识去解决不确定性问题的数学方法,对于一个计算机专业的人士,应当熟悉其应用在诸如机器翻译,语音识别,垃圾邮件检测等常见的计算机问题领域。", 27 | "title": "《贝叶斯思维》", 28 | "douban": "http://book.douban.com/subject/26340992/" 29 | }, 30 | { 31 | "id": 5, 32 | "description": "本书以机器学习与计算统计为主题背景,专门讲述如何挖掘和分析Web上的数据和资源,如何分析用户体验、市场营销、个人品味等诸多信息,并得出有用的结论,通过复杂的算法来从Web网站获取、收集并分析用户的数据和反馈信息,以便创造新的用户价值和商业价值。", 33 | "title": "《集体智慧编程》", 34 | "depends": [ 35 | 7 36 | ], 37 | "douban": "http://book.douban.com/subject/3288908/" 38 | }, 39 | { 40 | "id": 7, 41 | "description": "全面阐述了开发先进推荐系统的方法,其中呈现了许多经典算法,并讨论了如何衡量推荐系统的有效性。", 42 | "title": "《推荐系统》", 43 | "douban": "http://book.douban.com/subject/24746415/" 44 | }, 45 | { 46 | "id": 8, 47 | "description": "这本书很有意思,而且对读者要求不高。不需要知道什么是数据可视化,也不用有太多Web开发背景就能看懂它。", 48 | "title": "《数据可视化实战》", 49 | "depends": [ 50 | 3 51 | ], 52 | "douban": "http://book.douban.com/subject/24748670/" 53 | }, 54 | { 55 | "id": 9, 56 | "description": "本书涵盖了文本处理概念和技术的多个方面,包括文本预处理、搜索、字符串匹配、信息抽取、命名实体识别、分类、聚类、标签生成、摘要、问答等。本书的特点在于通过实例来理解文本处理的这些概念和技术,读者利用现有的开源工具就可以自己实现这些实例。", 57 | "title": "《驾驭文本:文本的发现、组织和处理》", 58 | "depends": [ 59 | 10 60 | ], 61 | "douban": "http://book.douban.com/subject/26582357/" 62 | }, 63 | { 64 | "id": 10, 65 | "description": "《Lucene in Action》", 66 | "title": "《Lucene in Action》", 67 | "douban": "http://book.douban.com/subject/1962641/" 68 | }, 69 | { 70 | "id": 11, 71 | "description": "《Python自然语言处理》是自然语言处理领域的一本实用入门指南,旨在帮助读者学习如何编写程序来分析书面语言。", 72 | "title": "《Python自然语言处理》", 73 | "depends": [ 74 | 9 75 | ], 76 | "douban": "http://book.douban.com/subject/25916599/" 77 | }, 78 | { 79 | "id": 12, 80 | "description": "通过精心编排的实例,切入日常工作任务,摒弃学术化语言,利用高效可复用的Python代码阐释如何处理统计数据,进行数据分析及可视化。读者可从中学到一些核心的机器学习算法,并将其运用于某些策略性任务中,如分类、预测及推荐等。", 81 | "title": "《机器学习实战》", 82 | "depends": [ 83 | 11, 5, 4, 3 84 | ], 85 | "douban": "http://book.douban.com/subject/24703171/" 86 | }, 87 | { 88 | "id": 13, 89 | "description": "基础理论与实践完美的结合,是一部逻辑紧密、内容详实,适合所有相关技术人员的参考书。", 90 | "title": "《机器学习:实用案例解析》", 91 | "depends": [ 92 | 12 93 | ], 94 | "douban": "http://book.douban.com/subject/24251326/" 95 | } 96 | ] 97 | } 98 | -------------------------------------------------------------------------------- /app/data/frontend.json: -------------------------------------------------------------------------------- 1 | { 2 | "books": [ 3 | { 4 | "id": 1, 5 | "description": "将对JavaScript追根溯源,从它在最早的Netscape浏览器中诞生谈起,一直谈到今天的它对DOM和AjaX的强大支持。读者将通过《JavaScript高级程序设计(第3版)》掌握如何运用和扩展这门语言,从而更好地满足自己的需求,以及如何实现客户端与服务器的无缝通信,而又不必求助于Java或隐藏的网页框架(frame元素)。", 6 | "title": "《JavaScript高级程序设计》", 7 | "douban": "http://book.douban.com/subject/10546125/" 8 | }, 9 | { 10 | "id": 2, 11 | "description": "经典权威的JavaScript工具书,是程序员学习核心JavaScript语言和由Web浏览器定义的JavaScript API的指南和综合参考手册。", 12 | "title": "《JavaScript权威指南》", 13 | "douban": "http://book.douban.com/subject/10549733/" 14 | }, 15 | { 16 | "id": 3, 17 | "description": "运用《编写可维护的JavaScript》中讲述的技巧和技术,可以使JavaScript团队编程从侠义的个人偏好的阴霾走出来,走向真正的高可维护性、高效能和高水准。它是一本构建编码风格手册,帮助开发团队从“游击队”走向“正规军”。", 18 | "title": "《编写可维护的JavaScript》", 19 | "depends": [ 20 | 4 21 | ], 22 | "douban": "http://book.douban.com/subject/21792530/" 23 | }, 24 | { 25 | "id": 4, 26 | "description": "您将会发现一门美丽的、优雅的、轻量级的和非常富有表现力的语言,它使您创建高效的代码,不管您编写代码的目的是管理对象库还是仅仅使Ajax运行得更快。", 27 | "title": "《JavaScript语言精粹》", 28 | "depends": [ 29 | 1, 2 30 | ], 31 | "douban": "http://book.douban.com/subject/11874748/" 32 | }, 33 | { 34 | "id": 5, 35 | "description": "通过现代浏览器原生的概念与代码,将这些工具带回视线。读者将理解jQuery在DOM脚本编写中扮演的角色,并学习如何在移动应用和特定浏览器中直接使用DOM编写应用程序。", 36 | "title": "《DOM启蒙》", 37 | "douban": "http://book.douban.com/subject/25882606/" 38 | }, 39 | { 40 | "id": 6, 41 | "description": "在简洁明快地讲述JavaScript和DOM的基本知识之后,通过几个实例演示了专业水准的网页开发技术,透彻阐述了平稳退化等一批至关重要的JavaScript编程原则和实践,并全面探讨了HTML5以及jQuery等JavaScript库。", 42 | "title": "《JavaScript DOM编程艺术》", 43 | "depends": [ 44 | 5 45 | ], 46 | "douban": "http://book.douban.com/subject/6038371/" 47 | }, 48 | { 49 | "id": 7, 50 | "description": "想要快速省力地做到让Web风格整齐划一吗?《CSS权威指南(第3版)》告诉你怎样将最新的CSS2以CSS2.1里面所定义的各种CSS元素应用到实际工作当中。通过书中的例子,你将学会怎样使用CSS创建或修改网站的外观,并且达到普通HTML无法实现的效果。", 51 | "title": "《CSS权威指南》", 52 | "douban": "http://book.douban.com/subject/2308234/" 53 | }, 54 | { 55 | "id": 8, 56 | "description": "详细地讲解了设计框架需要具备的知识,主要包括的内容为:框架与库、JavaScript框架分类、JavaScript框架的主要功能、种子模块、模块加载系统、语言模块、浏览器嗅探与特征侦测、样式的支持侦测、类工厂、JavaScript对类的支撑...", 57 | "title": "《JavaScript 框架设计》", 58 | "depends": [ 59 | 4 60 | ], 61 | "douban": "http://book.douban.com/subject/25858070/" 62 | }, 63 | { 64 | "id": 9, 65 | "description": "本书展示了从前端到后端都使用JavaScript来开发复杂的单页Web应用,你的团队能够很容易地进行设计、测试、维护和扩展,不会受到某个框架的限制。", 66 | "title": "《单页Web应用: JavaScript从前端到后端》", 67 | "depends": [ 68 | 6 69 | ], 70 | "douban": "http://book.douban.com/subject/25986284/" 71 | }, 72 | { 73 | "id": 10, 74 | "description": "《基于MVC的JavaScript Web富应用开发》所涵盖的知识点非常全面,从Mvc的基本理论到网络协议、从模块解耦到异步编程模型、从HTML5/CSS3到NodeJS、从软件测试到部署调试,对于很多前端工程师来说,这些知识正是突破自己的瓶颈所亟需的。", 75 | "title": "《基于MVC的JavaScript Web富应用开发》", 76 | "depends": [ 77 | 8, 9, 11 78 | ], 79 | "douban": "http://book.douban.com/subject/10733304/" 80 | }, 81 | { 82 | "id": 11, 83 | "description": "将最有用的CSS技术汇总在一起,还总结了CSS设计中的实践,讨论了解决各种实际问题的技术,填补了一直以来CSS图书的空白。", 84 | "title": "《精通CSS:高级Web标准解决方案》", 85 | "depends": [ 86 | 7 87 | ], 88 | "douban": "http://book.douban.com/subject/4736167/" 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Developer](https://github.com/phodal/developer)进阶书单 2 | 3 | 成长路线已经汇集到Growth,Github见:[https://github.com/phodal/growth](https://github.com/phodal/growth) 4 | 5 | > 这是一份关于如何[Re-Practise](https://github.com/phodal/repractise)的技术书籍推荐书单。 6 | 7 | 一直画/写一个推荐书单来供大家参考,无奈找不到一本合适的形式。有一天,想到了之前的技术树 [https://github.com/phodal/sherlock](https://github.com/phodal/sherlock),便开始落地了。 8 | 9 | 在线查看见:[http://phodal.github.io/booktree/](http://phodal.github.io/booktree/) 10 | 11 | 我深知自己的知识有限,所以写下本文以便和大家切磋交流。欢迎通过 GitHub 的Issues或者直接Pull Requests方式来分享你的经验。期待你的反馈。 12 | 13 | 基本阅读路线图: 14 | 15 | ![BookTree](app/booktree.png) 16 | 17 | 首先,你需要选择一门语言,然后学习之。这时有一些还不错,如JavaScript实战,JavaScript Cookbook,前者是一门实站手册,后者则是参考手册。再来一本某某语言,或者框架的实战,与权威指南,你就可以完成工作了。 18 | 19 | 然后呢? 20 | 21 | **说明**: 完成工作是一件很容易的事,如何更好地完成工作就需要更多地学习。并且我坚信每一个有技术热情的人,都希望可以看到自己写的框架可以无处不在。 22 | 23 | ### 《技术的本质》 - W. Brain Arthur早已看穿了一切 24 | 25 | 这是一本关于『技术是什么,它是如何进化』的书。新的技术是根据于我们当前的目的、一个可实现的原理、一种新现象而发明的。并且,新的技术都是基于之前的技术发展出来的。 26 | 27 | So,通过研究现有技术的一些发展,我们可以预料到一些新的技术的出现。尽管新的技术并没有解决一些根本性问题,如业务,但是它是为了业务而简化现有的技术。 28 | 29 | ### 如何写好代码——重构与设计模式 30 | 31 | 从编写可读的代码,到重构现有的代码,再到设计模式,是编码的必备法则。 32 | 33 | ![如何写好代码——重构与设计模式](screenshots/code.png) 34 | 35 | - 《测试驱动开发》: 尽管在国内,我们很少听到开发人员写测试,就更少听人们谈论TDD。虽然我不是TDD的死忠,但是我觉得TDD还是很有好处的。特别是当你的函数特别长的时候,它可以驱使你写出更短的函数——更多的函数。红->绿->重构,就是这么简单。 36 | - 《重构: 改善既有代码的设计》: 红->绿->重构。如果重构之前没有测试,我相信你可能是想换个工作了。好的代码是重构出来的,而不是一开始就写出来的——除非你的代码不用于任何业务。反正,就是程序员必读,不想多说。 37 | - 《Head First设计模式》: GoF的《设计模式》一书很薄,所以也很抽象。第一次看《设计模式》的时候,硬着头皮看了几天,然后放弃了。。。不过,Head First系列可以将各种枯燥的设计生起起来,这是一本非常适合入门设计模式的书籍没有之一。 38 | - 《设计模式解析》: 比Head First更深入,但是比DP简单。作者选用了一些常用或者说用到的模式,讲述了为什么在这里适合用它。 39 | - 《易读代码的艺术/编写可读代码的艺术》: 纳尼!你居然不想买这本书? 40 | - 《代码整洁之道》: 书中给了很方法与规范,遵循它们可以写出整洁的代码。但是整洁并不意味着你应该让代码简单! 41 | - 《重构与模式》: 这本书的中文名字应该叫《重构到模式》!!!重构代码到设计模式就这么简单。 42 | - 《设计模式》: 必读,并且值得多读几遍。 43 | - 《元素模式》: 首先书名很扯!!!这本书更适合叫《设计模式要素》!这本书提取了设计模式中的一些基本元素,很具有启发性。 44 | 45 | ### 如何写前端框架——前端读书路线图 46 | 47 | 以JavaScript作为例子来解释如何去学习一门语言,从语法到最后的MVC。 48 | 49 | ![如何写前端框架——前端读书路线图](screenshots/frontend.png) 50 | 51 | 本图已被《JavaScript 框架设计:第 2 版》收录。 52 | 53 | ### 机器学习读书路线 54 | 55 | 机器学习依赖于大量的数据和理论知识,而数据又可以创造出美妙的数据可视化图像。 56 | 57 | ![机器学习读书路线](screenshots/ml.png) 58 | 59 | 60 | ### 持续交付读书路线图 61 | 62 | 敏捷是过去,持续交付是现在,未来呢? 63 | 64 | 想要构建一个好的项目,构建系统、自动化测试、可配置缺一不可。 65 | 66 | ![持续交付读书路线图](screenshots/cd.png) 67 | 68 | ### 领域特定语言读书路线图 69 | 70 | 最好的语言就是可以表达你业务的语言。 71 | 72 | 如果你熟悉前端的知识的话,你会发现DSL无处不在。 73 | 74 | ![领域特定语言读书路线图](screenshots/dsl.png) 75 | 76 | ### 架构与模式读书路线图——每个人都是架构师。 77 | 78 | 成为架构师最简单的方法就是学习别人的模式。 79 | 80 | 成为成功架构师便是创建模式。 81 | 82 | ![架构与模式读书路线图](screenshots/arch.png) 83 | 84 | 85 | ## Contribute 86 | 87 | 书的数据代码位于``app/data``目录: 88 | 89 | - arch.json 架构 90 | - cd.json 持续交付 91 | - code.json 更好的代码 92 | - frontend.json 前端 93 | - lang.json 语言 94 | - ml.json 机器学习 95 | 96 | 基本格式如下: 97 | 98 | ```javascript 99 | { 100 | "id": 1, 101 | "description": "尽管在国内,我们很少听到开发人员写测试,就更少听人们谈论TDD。虽然我不是TDD的死忠,但是我觉得TDD还是很有好处的。特别是当你的函数特别长的时候,它可以驱使你写出更短的函数——更多的函数。红->绿->重构,就是这么简单。", 102 | "title": "《测试驱动开发》", 103 | "depends": [ 104 | 2, 3 105 | ] 106 | } 107 | ``` 108 | 109 | 字段说明: 110 | 111 | - ``id``用于寻找依赖用的 112 | - ``description`` 书籍的简单书评 113 | - ``title`` 书名 114 | - ``depends`` 依赖,数组,可多个 115 | 116 | ### License 117 | 118 | © 2015 [Phodal Huang](http://www.phodal.com). See `LICENSE.txt` in this directory. 119 | 120 | [待我代码编成,娶你为妻可好](http://www.xuntayizhan.com/person/ji-ke-ai-qing-zhi-er-shi-dai-wo-dai-ma-bian-cheng-qu-ni-wei-qi-ke-hao-wan/) 121 | -------------------------------------------------------------------------------- /app/scripts/render.js: -------------------------------------------------------------------------------- 1 | define(['d3', 'lib/knockout', 'scripts/Utils', 'dagre-d3', 'jquery', 'lettuce', 'text!templates/description.html', 'jquery.tooltipster'], 2 | function (d3, ko, Utils, dagreD3, $, Lettuce, description_template) { 3 | 'use strict'; 4 | function renderPage(books_data, elementId) { 5 | function setBookNode() { 6 | ko.utils.arrayForEach(books_data.books, function (book) { 7 | var value = book; 8 | value.label = book.title; 9 | value.height = 40; 10 | value.width = 200; 11 | value.rx = value.ry = 10; 12 | g.setNode(book.title, value); 13 | }); 14 | } 15 | 16 | function setBookEdge() { 17 | ko.utils.arrayForEach(books_data.books, function (book) { 18 | var book_id = book.id; 19 | if (book.depends) { 20 | ko.utils.arrayForEach(book.depends, function (id) { 21 | var dependents_name = Utils.getSkillById(books_data.books, id).title; 22 | var book_name = Utils.getSkillById(books_data.books, book_id).title; 23 | g.setEdge(dependents_name, book_name, {label: '', lineInterpolate: 'basis'}); 24 | }); 25 | } 26 | }); 27 | } 28 | 29 | function writeDownloadLink(id){ 30 | try { 31 | var isFileSaverSupported = !!new Blob(); 32 | } catch (e) { 33 | alert("blob not supported"); 34 | } 35 | 36 | var svg = document.getElementById(id); 37 | 38 | var serializer = new XMLSerializer(); 39 | var source = serializer.serializeToString(svg); 40 | 41 | if(!source.match(/^]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){ 42 | source = source.replace(/^]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){ 45 | source = source.replace(/^ 117 | 118 | -------------------------------------------------------------------------------- /app/assets/lang.svg: -------------------------------------------------------------------------------- 1 | 2 | 《编译原理》《编程语言实现模式》《编程之魂》《Ruby元编程》《领域专用语言实战》《领域特定语言》 -------------------------------------------------------------------------------- /app/styles/mifa.min.css: -------------------------------------------------------------------------------- 1 | .color-primary{color:#384452;background-color:#384452}.color-grey{color:#d1d8df;background-color:#d1d8df}.color-green{color:#1abc9c;background-color:#1abc9c}.color-dark-grey{color:#5e6772;background-color:#5e6772}.color-blue{color:#23B7F3;background-color:#23B7F3}.color-code-grey{color:#eef1f5;background-color:#eef1f5}.color-red{color:#f53d3d;background-color:#f53d3d}.color-yellow{color:#ffff3a;background-color:#ffff3a}.color-light-grey{color:#fdfdfd;background-color:#fdfdfd}*,*:after,*:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{color:#384452;font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", SimSun, sans-serif;font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6}blockquote{border-left:0.3rem solid #1abc9c;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin-bottom:0}q:before{color:#1abc9c;content:open-quote;font-size:4em;line-height:0.1em;margin-right:0.25em;vertical-align:-0.4em}q:after{content:none}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#384452;border:0.1rem solid #384452;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3.0rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:focus,.button:hover,button:focus,button:hover,input[type='button']:focus,input[type='button']:hover,input[type='reset']:focus,input[type='reset']:hover,input[type='submit']:focus,input[type='submit']:hover{background-color:#1abc9c;border-color:#1abc9c;color:#fff;outline:0}.button[disabled],button[disabled],input[type='button'][disabled],input[type='reset'][disabled],input[type='submit'][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type='button'][disabled]:focus,input[type='button'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='reset'][disabled]:hover,input[type='submit'][disabled]:focus,input[type='submit'][disabled]:hover{background-color:#384452;border-color:#384452}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{background-color:transparent;color:#384452}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type='button'].button-outline:focus,input[type='button'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='submit'].button-outline:focus,input[type='submit'].button-outline:hover{background-color:transparent;border-color:#1abc9c;color:#1abc9c}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='button'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='reset'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus,input[type='submit'].button-outline[disabled]:hover{border-color:inherit;color:#384452}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{background-color:transparent;border-color:transparent;color:#384452}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type='button'].button-clear:focus,input[type='button'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='submit'].button-clear:focus,input[type='submit'].button-clear:hover{background-color:transparent;border-color:transparent;color:#1abc9c}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='button'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='reset'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus,input[type='submit'].button-clear[disabled]:hover{color:#384452}code{background:#eef1f5;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.2rem .5rem;white-space:nowrap}pre{background:#eef1f5;border-left:0.3rem solid #1abc9c;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:0.1rem solid #384452;margin:3.0rem 0}input[type='email'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],input:not([type]),textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:0.1rem solid #d1d8df;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1.0rem;width:100%}input[type='email']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,input:not([type]):focus,textarea:focus,select:focus{border-color:#1abc9c;outline:0}select{background:url('data:image/svg+xml;utf8,') center right no-repeat;padding-right:3.0rem}select:focus{background-image:url('data:image/svg+xml;utf8,')}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{display:inline-block;font-weight:normal;margin-left:.5rem}.container{margin:0 auto;max-width:112.0rem;padding:0 2.0rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{-ms-grid-row-align:center;align-self:center}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1.0rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1.0rem}}img{max-width:100%}a{color:#1abc9c;text-decoration:none}a:focus,a:hover{color:#23B7F3}dl,ol,ul{list-style:none;margin-top:0;padding-left:0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3.0rem}ol{list-style:decimal inside}ul{list-style:circle inside}li{color:#384452}.button,button,dd,dt,li{margin-bottom:1.0rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;width:100%}table thead th,thead th{border-top:0.1rem solid #d1d8df;background:#fdfdfd}tbody tr:nth-child(even){background:#fdfdfd}tbody tr:nth-child(odd){background:#eef1f5}td,th{border-bottom:0.1rem solid #d1d8df;padding:1.2rem 1.5rem;text-align:left}u{text-decoration:none;border-bottom:1px dashed}a{text-decoration:none}u{background:#ffff3a}b,strong{font-weight:bold}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2.0rem;margin-top:0}h1{font-size:4.0rem;line-height:1.2}h2{font-size:3.2rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.4rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:2.0rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right} 2 | 3 | /*# sourceMappingURL=mifa.min.css.map */ -------------------------------------------------------------------------------- /app/assets/cd.svg: -------------------------------------------------------------------------------- 1 | 2 | 《敏捷软件开发:原则、模式与实践》《代码管理核心技术及实践》《软件测试的艺术》《Cucumber:行为驱动开发指南》《敏捷软件测试》《深入理解软件构造系统》《配置管理最佳实践》《持续交付:发布可靠软件的系统方法》 -------------------------------------------------------------------------------- /app/styles/tooltipster.css: -------------------------------------------------------------------------------- 1 | /* This is the default Tooltipster theme (feel free to modify or duplicate and create multiple themes!): */ 2 | .tooltipster-default { 3 | border-radius: 5px; 4 | border: 2px solid #ecf0f1; 5 | background: #384452; 6 | color: #fff; 7 | } 8 | 9 | /* Use this next selector to style things like font-size and line-height: */ 10 | .tooltipster-default .tooltipster-content { 11 | font-family: Arial, sans-serif; 12 | font-size: 14px; 13 | line-height: 16px; 14 | padding: 8px 10px; 15 | overflow: hidden; 16 | } 17 | 18 | /* This next selector defines the color of the border on the outside of the arrow. This will automatically match the color and size of the border set on the main tooltip styles. Set display: none; if you would like a border around the tooltip but no border around the arrow */ 19 | .tooltipster-default .tooltipster-arrow .tooltipster-arrow-border { 20 | /* border-color: ... !important; */ 21 | } 22 | 23 | 24 | /* If you're using the icon option, use this next selector to style them */ 25 | .tooltipster-icon { 26 | cursor: help; 27 | margin-left: 4px; 28 | } 29 | 30 | /* This is the base styling required to make all Tooltipsters work */ 31 | .tooltipster-base { 32 | padding: 0; 33 | font-size: 0; 34 | line-height: 0; 35 | position: absolute; 36 | left: 0; 37 | top: 0; 38 | z-index: 9999999; 39 | pointer-events: none; 40 | width: auto; 41 | overflow: visible; 42 | } 43 | .tooltipster-base .tooltipster-content { 44 | overflow: hidden; 45 | } 46 | 47 | 48 | /* These next classes handle the styles for the little arrow attached to the tooltip. By default, the arrow will inherit the same colors and border as what is set on the main tooltip itself. */ 49 | .tooltipster-arrow { 50 | display: block; 51 | text-align: center; 52 | width: 100%; 53 | height: 100%; 54 | position: absolute; 55 | top: 0; 56 | left: 0; 57 | z-index: -1; 58 | } 59 | .tooltipster-arrow span, .tooltipster-arrow-border { 60 | display: block; 61 | width: 0; 62 | height: 0; 63 | position: absolute; 64 | } 65 | .tooltipster-arrow-top span, .tooltipster-arrow-top-right span, .tooltipster-arrow-top-left span { 66 | border-left: 8px solid transparent !important; 67 | border-right: 8px solid transparent !important; 68 | border-top: 8px solid; 69 | bottom: -7px; 70 | } 71 | .tooltipster-arrow-top .tooltipster-arrow-border, .tooltipster-arrow-top-right .tooltipster-arrow-border, .tooltipster-arrow-top-left .tooltipster-arrow-border { 72 | border-left: 9px solid transparent !important; 73 | border-right: 9px solid transparent !important; 74 | border-top: 9px solid; 75 | bottom: -7px; 76 | } 77 | 78 | .tooltipster-arrow-bottom span, .tooltipster-arrow-bottom-right span, .tooltipster-arrow-bottom-left span { 79 | border-left: 8px solid transparent !important; 80 | border-right: 8px solid transparent !important; 81 | border-bottom: 8px solid; 82 | top: -7px; 83 | } 84 | .tooltipster-arrow-bottom .tooltipster-arrow-border, .tooltipster-arrow-bottom-right .tooltipster-arrow-border, .tooltipster-arrow-bottom-left .tooltipster-arrow-border { 85 | border-left: 9px solid transparent !important; 86 | border-right: 9px solid transparent !important; 87 | border-bottom: 9px solid; 88 | top: -7px; 89 | } 90 | .tooltipster-arrow-top span, .tooltipster-arrow-top .tooltipster-arrow-border, .tooltipster-arrow-bottom span, .tooltipster-arrow-bottom .tooltipster-arrow-border { 91 | left: 0; 92 | right: 0; 93 | margin: 0 auto; 94 | } 95 | .tooltipster-arrow-top-left span, .tooltipster-arrow-bottom-left span { 96 | left: 6px; 97 | } 98 | .tooltipster-arrow-top-left .tooltipster-arrow-border, .tooltipster-arrow-bottom-left .tooltipster-arrow-border { 99 | left: 5px; 100 | } 101 | .tooltipster-arrow-top-right span, .tooltipster-arrow-bottom-right span { 102 | right: 6px; 103 | } 104 | .tooltipster-arrow-top-right .tooltipster-arrow-border, .tooltipster-arrow-bottom-right .tooltipster-arrow-border { 105 | right: 5px; 106 | } 107 | .tooltipster-arrow-left span, .tooltipster-arrow-left .tooltipster-arrow-border { 108 | border-top: 8px solid transparent !important; 109 | border-bottom: 8px solid transparent !important; 110 | border-left: 8px solid; 111 | top: 50%; 112 | margin-top: -7px; 113 | right: -7px; 114 | } 115 | .tooltipster-arrow-left .tooltipster-arrow-border { 116 | border-top: 9px solid transparent !important; 117 | border-bottom: 9px solid transparent !important; 118 | border-left: 9px solid; 119 | margin-top: -8px; 120 | } 121 | .tooltipster-arrow-right span, .tooltipster-arrow-right .tooltipster-arrow-border { 122 | border-top: 8px solid transparent !important; 123 | border-bottom: 8px solid transparent !important; 124 | border-right: 8px solid; 125 | top: 50%; 126 | margin-top: -7px; 127 | left: -7px; 128 | } 129 | .tooltipster-arrow-right .tooltipster-arrow-border { 130 | border-top: 9px solid transparent !important; 131 | border-bottom: 9px solid transparent !important; 132 | border-right: 9px solid; 133 | margin-top: -8px; 134 | } 135 | 136 | 137 | /* Some CSS magic for the awesome animations - feel free to make your own custom animations and reference it in your Tooltipster settings! */ 138 | 139 | .tooltipster-fade { 140 | opacity: 0; 141 | -webkit-transition-property: opacity; 142 | -moz-transition-property: opacity; 143 | -o-transition-property: opacity; 144 | -ms-transition-property: opacity; 145 | transition-property: opacity; 146 | } 147 | .tooltipster-fade-show { 148 | opacity: 1; 149 | } 150 | 151 | .tooltipster-grow { 152 | -webkit-transform: scale(0,0); 153 | -moz-transform: scale(0,0); 154 | -o-transform: scale(0,0); 155 | -ms-transform: scale(0,0); 156 | transform: scale(0,0); 157 | -webkit-transition-property: -webkit-transform; 158 | -moz-transition-property: -moz-transform; 159 | -o-transition-property: -o-transform; 160 | -ms-transition-property: -ms-transform; 161 | transition-property: transform; 162 | -webkit-backface-visibility: hidden; 163 | } 164 | .tooltipster-grow-show { 165 | -webkit-transform: scale(1,1); 166 | -moz-transform: scale(1,1); 167 | -o-transform: scale(1,1); 168 | -ms-transform: scale(1,1); 169 | transform: scale(1,1); 170 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 171 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 172 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 173 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 174 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 175 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 176 | } 177 | 178 | .tooltipster-swing { 179 | opacity: 0; 180 | -webkit-transform: rotateZ(4deg); 181 | -moz-transform: rotateZ(4deg); 182 | -o-transform: rotateZ(4deg); 183 | -ms-transform: rotateZ(4deg); 184 | transform: rotateZ(4deg); 185 | -webkit-transition-property: -webkit-transform, opacity; 186 | -moz-transition-property: -moz-transform; 187 | -o-transition-property: -o-transform; 188 | -ms-transition-property: -ms-transform; 189 | transition-property: transform; 190 | } 191 | .tooltipster-swing-show { 192 | opacity: 1; 193 | -webkit-transform: rotateZ(0deg); 194 | -moz-transform: rotateZ(0deg); 195 | -o-transform: rotateZ(0deg); 196 | -ms-transform: rotateZ(0deg); 197 | transform: rotateZ(0deg); 198 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 1); 199 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 200 | -moz-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 201 | -ms-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 202 | -o-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 203 | transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); 204 | } 205 | 206 | .tooltipster-fall { 207 | top: 0; 208 | -webkit-transition-property: top; 209 | -moz-transition-property: top; 210 | -o-transition-property: top; 211 | -ms-transition-property: top; 212 | transition-property: top; 213 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 214 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 215 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 216 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 217 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 218 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 219 | } 220 | .tooltipster-fall-show { 221 | } 222 | .tooltipster-fall.tooltipster-dying { 223 | -webkit-transition-property: all; 224 | -moz-transition-property: all; 225 | -o-transition-property: all; 226 | -ms-transition-property: all; 227 | transition-property: all; 228 | top: 0px !important; 229 | opacity: 0; 230 | } 231 | 232 | .tooltipster-slide { 233 | left: -40px; 234 | -webkit-transition-property: left; 235 | -moz-transition-property: left; 236 | -o-transition-property: left; 237 | -ms-transition-property: left; 238 | transition-property: left; 239 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 240 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 241 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 242 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 243 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 244 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); 245 | } 246 | .tooltipster-slide.tooltipster-slide-show { 247 | } 248 | .tooltipster-slide.tooltipster-dying { 249 | -webkit-transition-property: all; 250 | -moz-transition-property: all; 251 | -o-transition-property: all; 252 | -ms-transition-property: all; 253 | transition-property: all; 254 | left: 0px !important; 255 | opacity: 0; 256 | } 257 | 258 | 259 | /* CSS transition for when contenting is changing in a tooltip that is still open. The only properties that will NOT transition are: width, height, top, and left */ 260 | .tooltipster-content-changing { 261 | opacity: 0.5; 262 | -webkit-transform: scale(1.1, 1.1); 263 | -moz-transform: scale(1.1, 1.1); 264 | -o-transform: scale(1.1, 1.1); 265 | -ms-transform: scale(1.1, 1.1); 266 | transform: scale(1.1, 1.1); 267 | } 268 | 269 | .tooltipster-shadow { 270 | border-radius: 5px; 271 | background: #fff; 272 | box-shadow: 0px 0px 14px rgba(0,0,0,0.3); 273 | color: #2c2c2c; 274 | } 275 | .tooltipster-shadow .tooltipster-content { 276 | font-family: 'Arial', sans-serif; 277 | font-size: 14px; 278 | line-height: 16px; 279 | padding: 8px 10px; 280 | } 281 | 282 | .tooltipster-base { 283 | width: 320px; 284 | } 285 | 286 | .tooltipster-content ul li { 287 | margin-left: -20px; 288 | } 289 | .tooltipster-content ul li { 290 | color: #ecf0f1; 291 | list-style: none; 292 | } 293 | 294 | .tooltipster-content ul li a{ 295 | color: #34495e; 296 | } 297 | 298 | .tooltipster-content ul li a:visited{ 299 | color: #34495e; 300 | } 301 | -------------------------------------------------------------------------------- /app/assets/code.svg: -------------------------------------------------------------------------------- 1 | 2 | 《测试驱动开发》《重构: 改善既有代码的设计》《Head First设计模式》《设计模式解析》《易读代码的艺术/编写可读代码的艺术》《代码整洁之道》《重构与模式》《设计模式》《元素模式》 -------------------------------------------------------------------------------- /app/assets/frontend.svg: -------------------------------------------------------------------------------- 1 | 2 | 《JavaScript高级程序设计》《JavaScript权威指南》《编写可维护的JavaScript》《JavaScript语言精粹》《DOM启蒙》《JavaScript DOM编程艺术》《CSS权威指南》《JavaScript 框架设计》《单页Web应用: JavaScript从前端到后端》《基于MVC的JavaScript Web富应用开发》《精通CSS:高级Web标准解决方案》 -------------------------------------------------------------------------------- /app/lib/text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license RequireJS text 2.0.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/requirejs/text for details 5 | */ 6 | /*jslint regexp: true */ 7 | /*global require: false, XMLHttpRequest: false, ActiveXObject: false, 8 | define: false, window: false, process: false, Packages: false, 9 | java: false, location: false */ 10 | 11 | define(['module'], function (module) { 12 | 'use strict'; 13 | 14 | var text, fs, 15 | progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], 16 | xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, 17 | bodyRegExp = /]*>\s*([\s\S]+)\s*<\/body>/im, 18 | hasLocation = typeof location !== 'undefined' && location.href, 19 | defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''), 20 | defaultHostName = hasLocation && location.hostname, 21 | defaultPort = hasLocation && (location.port || undefined), 22 | buildMap = [], 23 | masterConfig = (module.config && module.config()) || {}; 24 | 25 | text = { 26 | version: '2.0.5', 27 | 28 | strip: function (content) { 29 | //Strips declarations so that external SVG and XML 30 | //documents can be added to a document without worry. Also, if the string 31 | //is an HTML document, only the part inside the body tag is returned. 32 | if (content) { 33 | content = content.replace(xmlRegExp, ""); 34 | var matches = content.match(bodyRegExp); 35 | if (matches) { 36 | content = matches[1]; 37 | } 38 | } else { 39 | content = ""; 40 | } 41 | return content; 42 | }, 43 | 44 | jsEscape: function (content) { 45 | return content.replace(/(['\\])/g, '\\$1') 46 | .replace(/[\f]/g, "\\f") 47 | .replace(/[\b]/g, "\\b") 48 | .replace(/[\n]/g, "\\n") 49 | .replace(/[\t]/g, "\\t") 50 | .replace(/[\r]/g, "\\r") 51 | .replace(/[\u2028]/g, "\\u2028") 52 | .replace(/[\u2029]/g, "\\u2029"); 53 | }, 54 | 55 | createXhr: masterConfig.createXhr || function () { 56 | //Would love to dump the ActiveX crap in here. Need IE 6 to die first. 57 | var xhr, i, progId; 58 | if (typeof XMLHttpRequest !== "undefined") { 59 | return new XMLHttpRequest(); 60 | } else if (typeof ActiveXObject !== "undefined") { 61 | for (i = 0; i < 3; i += 1) { 62 | progId = progIds[i]; 63 | try { 64 | xhr = new ActiveXObject(progId); 65 | } catch (e) {} 66 | 67 | if (xhr) { 68 | progIds = [progId]; // so faster next time 69 | break; 70 | } 71 | } 72 | } 73 | 74 | return xhr; 75 | }, 76 | 77 | /** 78 | * Parses a resource name into its component parts. Resource names 79 | * look like: module/name.ext!strip, where the !strip part is 80 | * optional. 81 | * @param {String} name the resource name 82 | * @returns {Object} with properties "moduleName", "ext" and "strip" 83 | * where strip is a boolean. 84 | */ 85 | parseName: function (name) { 86 | var modName, ext, temp, 87 | strip = false, 88 | index = name.indexOf("."), 89 | isRelative = name.indexOf('./') === 0 || 90 | name.indexOf('../') === 0; 91 | 92 | if (index !== -1 && (!isRelative || index > 1)) { 93 | modName = name.substring(0, index); 94 | ext = name.substring(index + 1, name.length); 95 | } else { 96 | modName = name; 97 | } 98 | 99 | temp = ext || modName; 100 | index = temp.indexOf("!"); 101 | if (index !== -1) { 102 | //Pull off the strip arg. 103 | strip = temp.substring(index + 1) === "strip"; 104 | temp = temp.substring(0, index); 105 | if (ext) { 106 | ext = temp; 107 | } else { 108 | modName = temp; 109 | } 110 | } 111 | 112 | return { 113 | moduleName: modName, 114 | ext: ext, 115 | strip: strip 116 | }; 117 | }, 118 | 119 | xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, 120 | 121 | /** 122 | * Is an URL on another domain. Only works for browser use, returns 123 | * false in non-browser environments. Only used to know if an 124 | * optimized .js version of a text resource should be loaded 125 | * instead. 126 | * @param {String} url 127 | * @returns Boolean 128 | */ 129 | useXhr: function (url, protocol, hostname, port) { 130 | var uProtocol, uHostName, uPort, 131 | match = text.xdRegExp.exec(url); 132 | if (!match) { 133 | return true; 134 | } 135 | uProtocol = match[2]; 136 | uHostName = match[3]; 137 | 138 | uHostName = uHostName.split(':'); 139 | uPort = uHostName[1]; 140 | uHostName = uHostName[0]; 141 | 142 | return (!uProtocol || uProtocol === protocol) && 143 | (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) && 144 | ((!uPort && !uHostName) || uPort === port); 145 | }, 146 | 147 | finishLoad: function (name, strip, content, onLoad) { 148 | content = strip ? text.strip(content) : content; 149 | if (masterConfig.isBuild) { 150 | buildMap[name] = content; 151 | } 152 | onLoad(content); 153 | }, 154 | 155 | load: function (name, req, onLoad, config) { 156 | //Name has format: some.module.filext!strip 157 | //The strip part is optional. 158 | //if strip is present, then that means only get the string contents 159 | //inside a body tag in an HTML string. For XML/SVG content it means 160 | //removing the declarations so the content can be inserted 161 | //into the current doc without problems. 162 | 163 | // Do not bother with the work if a build and text will 164 | // not be inlined. 165 | if (config.isBuild && !config.inlineText) { 166 | onLoad(); 167 | return; 168 | } 169 | 170 | masterConfig.isBuild = config.isBuild; 171 | 172 | var parsed = text.parseName(name), 173 | nonStripName = parsed.moduleName + 174 | (parsed.ext ? '.' + parsed.ext : ''), 175 | url = req.toUrl(nonStripName), 176 | useXhr = (masterConfig.useXhr) || 177 | text.useXhr; 178 | 179 | //Load the text. Use XHR if possible and in a browser. 180 | if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) { 181 | text.get(url, function (content) { 182 | text.finishLoad(name, parsed.strip, content, onLoad); 183 | }, function (err) { 184 | if (onLoad.error) { 185 | onLoad.error(err); 186 | } 187 | }); 188 | } else { 189 | //Need to fetch the resource across domains. Assume 190 | //the resource has been optimized into a JS module. Fetch 191 | //by the module name + extension, but do not include the 192 | //!strip part to avoid file system issues. 193 | req([nonStripName], function (content) { 194 | text.finishLoad(parsed.moduleName + '.' + parsed.ext, 195 | parsed.strip, content, onLoad); 196 | }); 197 | } 198 | }, 199 | 200 | write: function (pluginName, moduleName, write, config) { 201 | if (buildMap.hasOwnProperty(moduleName)) { 202 | var content = text.jsEscape(buildMap[moduleName]); 203 | write.asModule(pluginName + "!" + moduleName, 204 | "define(function () { return '" + 205 | content + 206 | "';});\n"); 207 | } 208 | }, 209 | 210 | writeFile: function (pluginName, moduleName, req, write, config) { 211 | var parsed = text.parseName(moduleName), 212 | extPart = parsed.ext ? '.' + parsed.ext : '', 213 | nonStripName = parsed.moduleName + extPart, 214 | //Use a '.js' file name so that it indicates it is a 215 | //script that can be loaded across domains. 216 | fileName = req.toUrl(parsed.moduleName + extPart) + '.js'; 217 | 218 | //Leverage own load() method to load plugin value, but only 219 | //write out values that do not have the strip argument, 220 | //to avoid any potential issues with ! in file names. 221 | text.load(nonStripName, req, function (value) { 222 | //Use own write() method to construct full module value. 223 | //But need to create shell that translates writeFile's 224 | //write() to the right interface. 225 | var textWrite = function (contents) { 226 | return write(fileName, contents); 227 | }; 228 | textWrite.asModule = function (moduleName, contents) { 229 | return write.asModule(moduleName, fileName, contents); 230 | }; 231 | 232 | text.write(pluginName, nonStripName, textWrite, config); 233 | }, config); 234 | } 235 | }; 236 | 237 | if (masterConfig.env === 'node' || (!masterConfig.env && 238 | typeof process !== "undefined" && 239 | process.versions && 240 | !!process.versions.node)) { 241 | //Using special require.nodeRequire, something added by r.js. 242 | fs = require.nodeRequire('fs'); 243 | 244 | text.get = function (url, callback) { 245 | var file = fs.readFileSync(url, 'utf8'); 246 | //Remove BOM (Byte Mark Order) from utf8 files if it is there. 247 | if (file.indexOf('\uFEFF') === 0) { 248 | file = file.substring(1); 249 | } 250 | callback(file); 251 | }; 252 | } else if (masterConfig.env === 'xhr' || (!masterConfig.env && 253 | text.createXhr())) { 254 | text.get = function (url, callback, errback, headers) { 255 | var xhr = text.createXhr(), header; 256 | xhr.open('GET', url, true); 257 | 258 | //Allow plugins direct access to xhr headers 259 | if (headers) { 260 | for (header in headers) { 261 | if (headers.hasOwnProperty(header)) { 262 | xhr.setRequestHeader(header.toLowerCase(), headers[header]); 263 | } 264 | } 265 | } 266 | 267 | //Allow overrides specified in config 268 | if (masterConfig.onXhr) { 269 | masterConfig.onXhr(xhr, url); 270 | } 271 | 272 | xhr.onreadystatechange = function (evt) { 273 | var status, err; 274 | //Do not explicitly handle errors, those should be 275 | //visible via console output in the browser. 276 | if (xhr.readyState === 4) { 277 | status = xhr.status; 278 | if (status > 399 && status < 600) { 279 | //An http 4xx or 5xx error. Signal an error. 280 | err = new Error(url + ' HTTP status: ' + status); 281 | err.xhr = xhr; 282 | errback(err); 283 | } else { 284 | callback(xhr.responseText); 285 | } 286 | } 287 | }; 288 | xhr.send(null); 289 | }; 290 | } else if (masterConfig.env === 'rhino' || (!masterConfig.env && 291 | typeof Packages !== 'undefined' && typeof java !== 'undefined')) { 292 | //Why Java, why is this so awkward? 293 | text.get = function (url, callback) { 294 | var stringBuffer, line, 295 | encoding = "utf-8", 296 | file = new java.io.File(url), 297 | lineSeparator = java.lang.System.getProperty("line.separator"), 298 | input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), 299 | content = ''; 300 | try { 301 | stringBuffer = new java.lang.StringBuffer(); 302 | line = input.readLine(); 303 | 304 | // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 305 | // http://www.unicode.org/faq/utf_bom.html 306 | 307 | // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: 308 | // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 309 | if (line && line.length() && line.charAt(0) === 0xfeff) { 310 | // Eat the BOM, since we've already found the encoding on this file, 311 | // and we plan to concatenating this buffer with others; the BOM should 312 | // only appear at the top of a file. 313 | line = line.substring(1); 314 | } 315 | 316 | stringBuffer.append(line); 317 | 318 | while ((line = input.readLine()) !== null) { 319 | stringBuffer.append(lineSeparator); 320 | stringBuffer.append(line); 321 | } 322 | //Make sure we return a JavaScript string and not a Java string. 323 | content = String(stringBuffer.toString()); //String 324 | } finally { 325 | input.close(); 326 | } 327 | callback(content); 328 | }; 329 | } 330 | 331 | return text; 332 | }); 333 | -------------------------------------------------------------------------------- /app/assets/ml.svg: -------------------------------------------------------------------------------- 1 | 2 | 《Hadoop权威指南》《利用Python进行数据分析》《可视化数据》《贝叶斯思维》《集体智慧编程》《推荐系统》《数据可视化实战》《驾驭文本:文本的发现、组织和处理》《Lucene in Action》《Python自然语言处理》《机器学习实战》《机器学习:实用案例解析》 -------------------------------------------------------------------------------- /app/lib/lettuce.js: -------------------------------------------------------------------------------- 1 | /*global define */ 2 | (function(global, factory) { 3 | "use strict"; 4 | if (typeof module === "object" && typeof module.exports === "object") { 5 | module.exports = global.document ? 6 | factory(global, true) : 7 | function(w) { 8 | if (!w.document) { 9 | throw new Error("jQuery requires a window with a document"); 10 | } 11 | return factory(w); 12 | }; 13 | } else { 14 | factory(global); 15 | } 16 | 17 | }(typeof window !== "undefined" ? window : this, function(window, noGlobal) { 18 | 19 | 'use strict'; 20 | 21 | 22 | var Lettuce = function() {}; 23 | 24 | Lettuce.VERSION = '0.2.2'; 25 | 26 | window.lettuce = Lettuce; 27 | 28 | 29 | /* (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 30 | * Underscore may be freely distributed under the MIT license. 31 | */ 32 | 33 | Lettuce.isObject = function (obj) { 34 | var type = typeof obj; 35 | return type === 'function' || type === 'object' && !!obj; 36 | }; 37 | 38 | Lettuce.isFunction = function(obj) { 39 | return typeof obj == 'function' || false; 40 | }; 41 | 42 | Lettuce.defaults = function(obj) { 43 | if (!Lettuce.isObject(obj)) { 44 | return obj; 45 | } 46 | 47 | for (var i = 1, length = arguments.length; i < length; i++) { 48 | var source = arguments[i]; 49 | for (var prop in source) { 50 | if (obj[prop] === void 0) { 51 | obj[prop] = source[prop]; 52 | } 53 | } 54 | } 55 | return obj; 56 | }; 57 | 58 | Lettuce.extend = function (obj) { 59 | if (!Lettuce.isObject(obj)) { 60 | return obj; 61 | } 62 | var source, prop; 63 | for (var i = 1, length = arguments.length; i < length; i++) { 64 | source = arguments[i]; 65 | for (prop in source) { 66 | if (hasOwnProperty.call(source, prop)) { 67 | obj[prop] = source[prop]; 68 | } 69 | } 70 | } 71 | return obj; 72 | }; 73 | 74 | 75 | /** 76 | * Lettuce Class 0.0.1 77 | * JavaScript Class built-in inheritance system 78 | *(c) 2015, Fengda Huang - http://www.phodal.com 79 | * 80 | * Copyright (c) 2011, 2012 Jeanine Adkisson. 81 | * MIT Licensed. 82 | * Inspired by https://github.com/munro/self, https://github.com/jneen/pjs 83 | */ 84 | 85 | Lettuce.prototype.Class = (function (prototype, ownProperty) { 86 | 87 | var lettuceClass = function Klass(_superclass, definition) { 88 | 89 | function Class() { 90 | var self = this instanceof Class ? this : new Basic(); 91 | self.init.apply(self, arguments); 92 | return self; 93 | } 94 | 95 | function Basic() { 96 | } 97 | 98 | Class.Basic = Basic; 99 | 100 | var _super = Basic[prototype] = _superclass[prototype]; 101 | var proto = Basic[prototype] = Class[prototype] = new Basic(); 102 | 103 | proto.constructor = Class; 104 | 105 | Class.extend = function (def) { 106 | return new Klass(Class, def); 107 | }; 108 | 109 | var open = (Class.open = function (def) { 110 | if (Lettuce.isFunction(def)) { 111 | def = def.call(Class, proto, _super, Class, _superclass); 112 | } 113 | 114 | if (Lettuce.isObject(def)) { 115 | for (var key in def) { 116 | if (ownProperty.call(def, key)) { 117 | proto[key] = def[key]; 118 | } 119 | } 120 | } 121 | 122 | if (!('init' in proto)) { 123 | proto.init = _superclass; 124 | } 125 | 126 | return Class; 127 | }); 128 | 129 | return (open)(definition); 130 | }; 131 | 132 | return lettuceClass; 133 | 134 | })('prototype', ({}).hasOwnProperty); 135 | 136 | 137 | var Parser = new Lettuce.prototype.Class({}); 138 | 139 | Parser.prototype.init = function (options) { 140 | this.options = options || {}; 141 | Lettuce.defaults(this.options, { 142 | first: 'first', 143 | regex: /.*Page/, 144 | last: 'last' 145 | }); 146 | }; 147 | 148 | Parser.prototype.run = function (methods) { 149 | var self = this; 150 | self.methods = methods; 151 | self.execute(self.options.first); 152 | for (var key in self.methods) { 153 | if (key !== self.options.last && key.match(self.options.regex)) { 154 | this.execute(key); 155 | } 156 | } 157 | 158 | self.execute(self.options.last); 159 | }; 160 | 161 | Parser.prototype.execute = function (methodName) { 162 | this.methods[methodName](); 163 | }; 164 | 165 | var parser = { 166 | Parser: Parser 167 | }; 168 | 169 | Lettuce.prototype = Lettuce.extend(Lettuce.prototype, parser); 170 | 171 | 172 | Lettuce.get = function (url, callback) { 173 | Lettuce.send(url, 'GET', callback); 174 | }; 175 | 176 | Lettuce.load = function (url, callback) { 177 | Lettuce.send(url, 'GET', callback); 178 | }; 179 | 180 | Lettuce.post = function (url, data, callback) { 181 | Lettuce.send(url, 'POST', callback, data); 182 | }; 183 | 184 | Lettuce.send = function (url, method, callback, data) { 185 | data = data || null; 186 | var request = new XMLHttpRequest(); 187 | if (callback instanceof Function) { 188 | request.onreadystatechange = function () { 189 | if (request.readyState === 4 && (request.status === 200 || request.status === 0)) { 190 | callback(request.responseText); 191 | } 192 | }; 193 | } 194 | request.open(method, url, true); 195 | if (data instanceof Object) { 196 | data = JSON.stringify(data); 197 | request.setRequestHeader('Content-Type', 'application/json'); 198 | } 199 | request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 200 | request.send(data); 201 | }; 202 | 203 | 204 | var Event = { 205 | on: function(event, callback){ 206 | this._events = this._events || {}; 207 | this._events[event] = this._events[event] || []; 208 | this._events[event].push(callback); 209 | }, 210 | off: function(event, callback){ 211 | this._events = this._events || {}; 212 | if (event in this._events === false) { 213 | return; 214 | } 215 | this._events[event].splice(this._events[event].indexOf(callback), 1); 216 | }, 217 | trigger: function(event){ 218 | this._events = this._events || {}; 219 | if (event in this._events === false) { 220 | return; 221 | } 222 | for (var i = 0; i < this._events[event].length; i++) { 223 | this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1)); 224 | } 225 | } 226 | }; 227 | 228 | var event = { 229 | Event: Event 230 | }; 231 | 232 | 233 | Lettuce.prototype = Lettuce.extend(Lettuce.prototype, event); 234 | 235 | 236 | /* 237 | * JavaScript Templates 2.4.1 238 | * https://github.com/blueimp/JavaScript-Templates 239 | * 240 | * Copyright 2011, Sebastian Tschan 241 | * https://blueimp.net 242 | * 243 | * Licensed under the MIT license: 244 | * http://www.opensource.org/licenses/MIT 245 | * 246 | * Inspired by John Resig's JavaScript Micro-Templating: 247 | * http://ejohn.org/blog/javascript-micro-templating/ 248 | */ 249 | 250 | /*jslint evil: true, regexp: true, unparam: true */ 251 | 252 | var Template = { 253 | regexp: /([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g, 254 | encReg: /[<>&"'\x00]/g, 255 | encMap: { 256 | "<": "<", 257 | ">": ">", 258 | "&": "&", 259 | "\"": """, 260 | "'": "'" 261 | }, 262 | arg: "o", 263 | helper: ",print=function(s,e){_s+=e?(s==null?'':s):_e(s);}" + 264 | ",include=function(s,d){_s+=tmpl(s,d);}", 265 | 266 | tmpl: function (str, data){ 267 | var f = !/[^\w\-\.:]/.test(str) ? "" : this.compile(str); 268 | return f(data, this); 269 | }, 270 | 271 | compile: function (str) { 272 | var fn, variable; 273 | variable = this.arg + ',tmpl'; 274 | fn = "var _e=tmpl.encode" + this.helper + ",_s='" + str.replace(this.regexp, this.func) + "';"; 275 | fn = fn + "return _s;"; 276 | return new Function(variable, fn); 277 | }, 278 | 279 | encode: function (s) { 280 | /*jshint eqnull:true */ 281 | var encodeRegex = /[<>&"'\x00]/g, 282 | encodeMap = { 283 | "<": "<", 284 | ">": ">", 285 | "&": "&", 286 | "\"": """, 287 | "'": "'" 288 | }; 289 | return (s == null ? "" : "" + s).replace( 290 | encodeRegex, 291 | function (c) { 292 | return encodeMap[c] || ""; 293 | } 294 | ); 295 | }, 296 | 297 | func: function (s, p1, p2, p3, p4, p5) { 298 | var specialCharMAP = { 299 | "\n": "\\n", 300 | "\r": "\\r", 301 | "\t": "\\t", 302 | " ": " " 303 | }; 304 | 305 | if (p1) { // whitespace, quote and backspace in HTML context 306 | return specialCharMAP[p1] || "\\" + p1; 307 | } 308 | if (p2) { // interpolation: {%=prop%}, or unescaped: {%#prop%} 309 | if (p2 === "=") { 310 | return "'+_e(" + p3 + ")+'"; 311 | } 312 | return "'+(" + p3 + "==null?'':" + p3 + ")+'"; 313 | } 314 | if (p4) { // evaluation start tag: {% 315 | return "';"; 316 | } 317 | if (p5) { // evaluation end tag: %} 318 | return "_s+='"; 319 | } 320 | } 321 | }; 322 | 323 | var template = { 324 | Template: Template 325 | }; 326 | 327 | Lettuce.prototype = Lettuce.extend(Lettuce.prototype, template); 328 | 329 | 330 | /* 331 | * Copyright 2012-2013 (c) Pierre Duquesne 332 | * Licensed under the New BSD License. 333 | * https://github.com/stackp/promisejs 334 | */ 335 | 336 | function Promise() { 337 | this._callbacks = []; 338 | } 339 | 340 | Promise.prototype.then = function(func, context) { 341 | var p; 342 | if (this._isdone) { 343 | p = func.apply(context, this.result); 344 | } else { 345 | p = new Promise(); 346 | this._callbacks.push(function () { 347 | var res = func.apply(context, arguments); 348 | if (res && typeof res.then === 'function') { 349 | res.then(p.done, p); 350 | } 351 | }); 352 | } 353 | return p; 354 | }; 355 | 356 | Promise.prototype.done = function() { 357 | this.result = arguments; 358 | this._isdone = true; 359 | for (var i = 0; i < this._callbacks.length; i++) { 360 | this._callbacks[i].apply(null, arguments); 361 | } 362 | this._callbacks = []; 363 | }; 364 | 365 | var promise = { 366 | Promise: Promise 367 | }; 368 | 369 | Lettuce.prototype = Lettuce.extend(Lettuce.prototype, promise); 370 | 371 | 372 | var FX = { 373 | easing: { 374 | linear: function(progress) { 375 | return progress; 376 | }, 377 | quadratic: function(progress) { 378 | return Math.pow(progress, 2); 379 | }, 380 | swing: function(progress) { 381 | return 0.5 - Math.cos(progress * Math.PI) / 2; 382 | }, 383 | circ: function(progress) { 384 | return 1 - Math.sin(Math.acos(progress)); 385 | }, 386 | back: function(progress, x) { 387 | return Math.pow(progress, 2) * ((x + 1) * progress - x); 388 | }, 389 | bounce: function(progress) { 390 | for (var a = 0, b = 1; 1; a += b, b /= 2) { 391 | if (progress >= (7 - 4 * a) / 11) { 392 | return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2); 393 | } 394 | } 395 | }, 396 | elastic: function(progress, x) { 397 | return Math.pow(2, 10 * (progress - 1)) * Math.cos(20 * Math.PI * x / 3 * progress); 398 | } 399 | }, 400 | animate: function(options) { 401 | var start = new Date(); 402 | var id = setInterval(function() { 403 | var timePassed = new Date() - start; 404 | var progress = timePassed / options.duration; 405 | if (progress > 1) { 406 | progress = 1; 407 | } 408 | options.progress = progress; 409 | var delta = options.delta(progress); 410 | options.step(delta); 411 | if (progress == 1) { 412 | clearInterval(id); 413 | options.complete(); 414 | } 415 | }, options.delay || 10); 416 | }, 417 | fadeOut: function(element, options) { 418 | var to = 1; 419 | this.animate({ 420 | duration: options.duration, 421 | delta: function(progress) { 422 | progress = this.progress; 423 | return FX.easing.swing(progress); 424 | }, 425 | complete: options.complete, 426 | step: function(delta) { 427 | element.style.opacity = to - delta; 428 | } 429 | }); 430 | }, 431 | fadeIn: function(element, options) { 432 | var to = 0; 433 | this.animate({ 434 | duration: options.duration, 435 | delta: function(progress) { 436 | progress = this.progress; 437 | return FX.easing.swing(progress); 438 | }, 439 | complete: options.complete, 440 | step: function(delta) { 441 | element.style.opacity = to + delta; 442 | } 443 | }); 444 | } 445 | }; 446 | 447 | var fx = { 448 | FX: FX 449 | }; 450 | 451 | Lettuce.prototype = Lettuce.extend(Lettuce.prototype, fx); 452 | 453 | 454 | /* 455 | *Inspired by http://krasimirtsonev.com/blog/article/A-modern-JavaScript-router-in-100-lines-history-api-pushState-hash-url 456 | * Backbone 457 | */ 458 | var Router = { 459 | routes: [], 460 | hashStrip: /^#*/, 461 | location: window.location, 462 | 463 | getFragment: function () { 464 | return (this.location).hash.replace(this.hashStrip, ''); 465 | }, 466 | 467 | add: function (regex, handler) { 468 | if (Lettuce.isFunction(regex)) { 469 | handler = regex; 470 | regex = ''; 471 | } 472 | this.routes.push({regex: regex, handler: handler}); 473 | return this; 474 | }, 475 | 476 | check: function (self) { 477 | var fragment = self.getFragment(); 478 | for (var i = 0; i < self.routes.length; i++) { 479 | var newFragment = "#" + fragment; 480 | var match = newFragment.match(self.routes[i].regex); 481 | if (match) { 482 | match.shift(); 483 | self.routes[i].handler.apply({}, match); 484 | } 485 | } 486 | }, 487 | 488 | load: function () { 489 | var self, checkUrl; 490 | self = this; 491 | 492 | checkUrl = function () { 493 | self.check(self); 494 | }; 495 | 496 | function addEventListener() { 497 | if (window.addEventListener) { 498 | window.addEventListener("hashchange", checkUrl, false); 499 | } 500 | else if (window.attachEvent) { 501 | window.attachEvent("onhashchange", checkUrl); 502 | } 503 | } 504 | 505 | addEventListener(); 506 | return this; 507 | }, 508 | 509 | navigate: function (path) { 510 | path = path ? path : ''; 511 | this.location.href.match(/#(.*)$/); 512 | this.location.href = this.location.href.replace(/#(.*)$/, '') + '#' + path; 513 | return this; 514 | } 515 | }; 516 | 517 | var router = { 518 | Router: Router 519 | }; 520 | 521 | Lettuce.prototype = Lettuce.extend(Lettuce.prototype, router); 522 | 523 | 524 | if (typeof define === "function" && define.amd) { 525 | define("lettuce", [], function () { 526 | return Lettuce; 527 | }); 528 | } 529 | var strundefined = typeof undefined; 530 | if (typeof noGlobal === strundefined) { 531 | window.Lettuce = Lettuce; 532 | } 533 | return Lettuce; 534 | })); 535 | 536 | -------------------------------------------------------------------------------- /app/lib/underscore-min.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.8.2 2 | // http://underscorejs.org 3 | // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 | // Underscore may be freely distributed under the MIT license. 5 | (function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=d(e,i,4);var o=!w(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=b(r,e);for(var u=null!=t&&t.length,i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t){var r=S.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||o,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=S[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var e=this,u=e._,i=Array.prototype,o=Object.prototype,a=Function.prototype,c=i.push,l=i.slice,f=o.toString,s=o.hasOwnProperty,p=Array.isArray,h=Object.keys,v=a.bind,g=Object.create,y=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):e._=m,m.VERSION="1.8.2";var d=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},b=function(n,t,r){return null==n?m.identity:m.isFunction(n)?d(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return b(n,t,1/0)};var x=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var l=o[c];t&&r[l]!==void 0||(r[l]=i[l])}return r}},_=function(n){if(!m.isObject(n))return{};if(g)return g(n);y.prototype=n;var t=new y;return y.prototype=null,t},j=Math.pow(2,53)-1,w=function(n){var t=n&&n.length;return"number"==typeof t&&t>=0&&j>=t};m.each=m.forEach=function(n,t,r){t=d(t,r);var e,u;if(w(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=b(t,r);for(var e=!w(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=w(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=b(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(b(t)),r)},m.every=m.all=function(n,t,r){t=b(t,r);for(var e=!w(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=b(t,r);for(var e=!w(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r){return w(n)||(n=m.values(n)),m.indexOf(n,t,"number"==typeof r&&r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=w(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=b(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=w(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=b(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=w(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(w(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=b(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var A=function(n){return function(t,r,e){var u={};return r=b(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=A(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=A(function(n,t,r){n[r]=t}),m.countBy=A(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):w(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:w(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=b(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var k=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=n&&n.length;a>o;o++){var c=n[o];if(w(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=k(c,t,r));var l=0,f=c.length;for(u.length+=f;f>l;)u[i++]=c[l++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return k(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){if(null==n)return[];m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=b(r,e));for(var u=[],i=[],o=0,a=n.length;a>o;o++){var c=n[o],l=r?r(c,o,n):c;t?(o&&i===l||u.push(c),i=l):r?m.contains(i,l)||(i.push(l),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(k(arguments,!0,!0))},m.intersection=function(n){if(null==n)return[];for(var t=[],r=arguments.length,e=0,u=n.length;u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=k(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,"length").length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=n&&n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.indexOf=function(n,t,r){var e=0,u=n&&n.length;if("number"==typeof r)e=0>r?Math.max(0,u+r):r;else if(r&&u)return e=m.sortedIndex(n,t),n[e]===t?e:-1;if(t!==t)return m.findIndex(l.call(n,e),m.isNaN);for(;u>e;e++)if(n[e]===t)return e;return-1},m.lastIndexOf=function(n,t,r){var e=n?n.length:0;if("number"==typeof r&&(e=0>r?e+r+1:Math.min(e,r+1)),t!==t)return m.findLastIndex(l.call(n,0,e),m.isNaN);for(;--e>=0;)if(n[e]===t)return e;return-1},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=b(r,e,1);for(var u=r(t),i=0,o=n.length;o>i;){var a=Math.floor((i+o)/2);r(n[a])i;i++,n+=r)u[i]=n;return u};var O=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=_(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(v&&n.bind===v)return v.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return O(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var l=m.now();a||r.leading!==!1||(a=l);var f=t-(l-a);return e=this,u=arguments,0>=f||f>t?(o&&(clearTimeout(o),o=null),a=l,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,f)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var l=m.now()-o;t>l&&l>=0?e=setTimeout(c,t-l):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var F=!{toString:null}.propertyIsEnumerable("toString"),S=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(h)return h(n);var t=[];for(var e in n)m.has(n,e)&&t.push(e);return F&&r(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var e in n)t.push(e);return F&&r(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=b(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=x(m.allKeys),m.extendOwn=m.assign=x(m.keys),m.findKey=function(n,t,r){t=b(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=d(t,r)):(u=k(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var l=u[a],f=o[l];e(f,l,o)&&(i[l]=f)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(k(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=x(m.allKeys,!0),m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var E=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=f.call(n);if(u!==f.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!E(n[c],t[c],r,e))return!1}else{var l,s=m.keys(n);if(c=s.length,m.keys(t).length!==c)return!1;for(;c--;)if(l=s[c],!m.has(t,l)||!E(n[l],t[l],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return E(n,t)},m.isEmpty=function(n){return null==n?!0:w(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=p||function(n){return"[object Array]"===f.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return f.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===f.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&s.call(n,t)},m.noConflict=function(){return e._=u,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=function(n){return function(t){return null==t?void 0:t[n]}},m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=d(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var M={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},N=m.invert(M),I=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=I(M),m.unescape=I(N),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var B=0;m.uniqueId=function(n){var t=++B+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,R={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},q=/\\|'|\r|\n|\u2028|\u2029/g,K=function(n){return"\\"+R[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||T).source,(t.interpolate||T).source,(t.evaluate||T).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(q,K),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},l=t.variable||"obj";return c.source="function("+l+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var z=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return c.apply(n,arguments),z(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=i[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],z(this,r)}}),m.each(["concat","join","slice"],function(n){var t=i[n];m.prototype[n]=function(){return z(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this); 6 | //# sourceMappingURL=underscore-min.map -------------------------------------------------------------------------------- /app/lib/jquery.tooltipster.min.js: -------------------------------------------------------------------------------- 1 | /* Tooltipster v3.3.0 */;(function(e,t,n){function s(t,n){this.bodyOverflowX;this.callbacks={hide:[],show:[]};this.checkInterval=null;this.Content;this.$el=e(t);this.$elProxy;this.elProxyPosition;this.enabled=true;this.options=e.extend({},i,n);this.mouseIsOverProxy=false;this.namespace="tooltipster-"+Math.round(Math.random()*1e5);this.Status="hidden";this.timerHide=null;this.timerShow=null;this.$tooltip;this.options.iconTheme=this.options.iconTheme.replace(".","");this.options.theme=this.options.theme.replace(".","");this._init()}function o(t,n){var r=true;e.each(t,function(e,i){if(typeof n[e]==="undefined"||t[e]!==n[e]){r=false;return false}});return r}function f(){return!a&&u}function l(){var e=n.body||n.documentElement,t=e.style,r="transition";if(typeof t[r]=="string"){return true}v=["Moz","Webkit","Khtml","O","ms"],r=r.charAt(0).toUpperCase()+r.substr(1);for(var i=0;i');t.$elProxy.text(t.options.icon)}else{if(t.options.iconCloning)t.$elProxy=t.options.icon.clone(true);else t.$elProxy=t.options.icon}t.$elProxy.insertAfter(t.$el)}else{t.$elProxy=t.$el}if(t.options.trigger=="hover"){t.$elProxy.on("mouseenter."+t.namespace,function(){if(!f()||t.options.touchDevices){t.mouseIsOverProxy=true;t._show()}}).on("mouseleave."+t.namespace,function(){if(!f()||t.options.touchDevices){t.mouseIsOverProxy=false}});if(u&&t.options.touchDevices){t.$elProxy.on("touchstart."+t.namespace,function(){t._showNow()})}}else if(t.options.trigger=="click"){t.$elProxy.on("click."+t.namespace,function(){if(!f()||t.options.touchDevices){t._show()}})}}},_show:function(){var e=this;if(e.Status!="shown"&&e.Status!="appearing"){if(e.options.delay){e.timerShow=setTimeout(function(){if(e.options.trigger=="click"||e.options.trigger=="hover"&&e.mouseIsOverProxy){e._showNow()}},e.options.delay)}else e._showNow()}},_showNow:function(n){var r=this;r.options.functionBefore.call(r.$el,r.$el,function(){if(r.enabled&&r.Content!==null){if(n)r.callbacks.show.push(n);r.callbacks.hide=[];clearTimeout(r.timerShow);r.timerShow=null;clearTimeout(r.timerHide);r.timerHide=null;if(r.options.onlyOne){e(".tooltipstered").not(r.$el).each(function(t,n){var r=e(n),i=r.data("tooltipster-ns");e.each(i,function(e,t){var n=r.data(t),i=n.status(),s=n.option("autoClose");if(i!=="hidden"&&i!=="disappearing"&&s){n.hide()}})})}var i=function(){r.Status="shown";e.each(r.callbacks.show,function(e,t){t.call(r.$el)});r.callbacks.show=[]};if(r.Status!=="hidden"){var s=0;if(r.Status==="disappearing"){r.Status="appearing";if(l()){r.$tooltip.clearQueue().removeClass("tooltipster-dying").addClass("tooltipster-"+r.options.animation+"-show");if(r.options.speed>0)r.$tooltip.delay(r.options.speed);r.$tooltip.queue(i)}else{r.$tooltip.stop().fadeIn(i)}}else if(r.Status==="shown"){i()}}else{r.Status="appearing";var s=r.options.speed;r.bodyOverflowX=e("body").css("overflow-x");e("body").css("overflow-x","hidden");var o="tooltipster-"+r.options.animation,a="-webkit-transition-duration: "+r.options.speed+"ms; -webkit-animation-duration: "+r.options.speed+"ms; -moz-transition-duration: "+r.options.speed+"ms; -moz-animation-duration: "+r.options.speed+"ms; -o-transition-duration: "+r.options.speed+"ms; -o-animation-duration: "+r.options.speed+"ms; -ms-transition-duration: "+r.options.speed+"ms; -ms-animation-duration: "+r.options.speed+"ms; transition-duration: "+r.options.speed+"ms; animation-duration: "+r.options.speed+"ms;",f=r.options.minWidth?"min-width:"+Math.round(r.options.minWidth)+"px;":"",c=r.options.maxWidth?"max-width:"+Math.round(r.options.maxWidth)+"px;":"",h=r.options.interactive?"pointer-events: auto;":"";r.$tooltip=e('
');if(l())r.$tooltip.addClass(o);r._content_insert();r.$tooltip.appendTo("body");r.reposition();r.options.functionReady.call(r.$el,r.$el,r.$tooltip);if(l()){r.$tooltip.addClass(o+"-show");if(r.options.speed>0)r.$tooltip.delay(r.options.speed);r.$tooltip.queue(i)}else{r.$tooltip.css("display","none").fadeIn(r.options.speed,i)}r._interval_set();e(t).on("scroll."+r.namespace+" resize."+r.namespace,function(){r.reposition()});if(r.options.autoClose){e("body").off("."+r.namespace);if(r.options.trigger=="hover"){if(u){setTimeout(function(){e("body").on("touchstart."+r.namespace,function(){r.hide()})},0)}if(r.options.interactive){if(u){r.$tooltip.on("touchstart."+r.namespace,function(e){e.stopPropagation()})}var p=null;r.$elProxy.add(r.$tooltip).on("mouseleave."+r.namespace+"-autoClose",function(){clearTimeout(p);p=setTimeout(function(){r.hide()},r.options.interactiveTolerance)}).on("mouseenter."+r.namespace+"-autoClose",function(){clearTimeout(p)})}else{r.$elProxy.on("mouseleave."+r.namespace+"-autoClose",function(){r.hide()})}if(r.options.hideOnClick){r.$elProxy.on("click."+r.namespace+"-autoClose",function(){r.hide()})}}else if(r.options.trigger=="click"){setTimeout(function(){e("body").on("click."+r.namespace+" touchstart."+r.namespace,function(){r.hide()})},0);if(r.options.interactive){r.$tooltip.on("click."+r.namespace+" touchstart."+r.namespace,function(e){e.stopPropagation()})}}}}if(r.options.timer>0){r.timerHide=setTimeout(function(){r.timerHide=null;r.hide()},r.options.timer+s)}}})},_interval_set:function(){var t=this;t.checkInterval=setInterval(function(){if(e("body").find(t.$el).length===0||e("body").find(t.$elProxy).length===0||t.Status=="hidden"||e("body").find(t.$tooltip).length===0){if(t.Status=="shown"||t.Status=="appearing")t.hide();t._interval_cancel()}else{if(t.options.positionTracker){var n=t._repositionInfo(t.$elProxy),r=false;if(o(n.dimension,t.elProxyPosition.dimension)){if(t.$elProxy.css("position")==="fixed"){if(o(n.position,t.elProxyPosition.position))r=true}else{if(o(n.offset,t.elProxyPosition.offset))r=true}}if(!r){t.reposition();t.options.positionTrackerCallback.call(t,t.$el)}}}},200)},_interval_cancel:function(){clearInterval(this.checkInterval);this.checkInterval=null},_content_set:function(e){if(typeof e==="object"&&e!==null&&this.options.contentCloning){e=e.clone(true)}this.Content=e},_content_insert:function(){var e=this,t=this.$tooltip.find(".tooltipster-content");if(typeof e.Content==="string"&&!e.options.contentAsHTML){t.text(e.Content)}else{t.empty().append(e.Content)}},_update:function(e){var t=this;t._content_set(e);if(t.Content!==null){if(t.Status!=="hidden"){t._content_insert();t.reposition();if(t.options.updateAnimation){if(l()){t.$tooltip.css({width:"","-webkit-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms","-moz-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms","-o-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms","-ms-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms",transition:"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms"}).addClass("tooltipster-content-changing");setTimeout(function(){if(t.Status!="hidden"){t.$tooltip.removeClass("tooltipster-content-changing");setTimeout(function(){if(t.Status!=="hidden"){t.$tooltip.css({"-webkit-transition":t.options.speed+"ms","-moz-transition":t.options.speed+"ms","-o-transition":t.options.speed+"ms","-ms-transition":t.options.speed+"ms",transition:t.options.speed+"ms"})}},t.options.speed)}},t.options.speed)}else{t.$tooltip.fadeTo(t.options.speed,.5,function(){if(t.Status!="hidden"){t.$tooltip.fadeTo(t.options.speed,1)}})}}}}else{t.hide()}},_repositionInfo:function(e){return{dimension:{height:e.outerHeight(false),width:e.outerWidth(false)},offset:e.offset(),position:{left:parseInt(e.css("left")),top:parseInt(e.css("top"))}}},hide:function(n){var r=this;if(n)r.callbacks.hide.push(n);r.callbacks.show=[];clearTimeout(r.timerShow);r.timerShow=null;clearTimeout(r.timerHide);r.timerHide=null;var i=function(){e.each(r.callbacks.hide,function(e,t){t.call(r.$el)});r.callbacks.hide=[]};if(r.Status=="shown"||r.Status=="appearing"){r.Status="disappearing";var s=function(){r.Status="hidden";if(typeof r.Content=="object"&&r.Content!==null){r.Content.detach()}r.$tooltip.remove();r.$tooltip=null;e(t).off("."+r.namespace);e("body").off("."+r.namespace).css("overflow-x",r.bodyOverflowX);e("body").off("."+r.namespace);r.$elProxy.off("."+r.namespace+"-autoClose");r.options.functionAfter.call(r.$el,r.$el);i()};if(l()){r.$tooltip.clearQueue().removeClass("tooltipster-"+r.options.animation+"-show").addClass("tooltipster-dying");if(r.options.speed>0)r.$tooltip.delay(r.options.speed);r.$tooltip.queue(s)}else{r.$tooltip.stop().fadeOut(r.options.speed,s)}}else if(r.Status=="hidden"){i()}return r},show:function(e){this._showNow(e);return this},update:function(e){return this.content(e)},content:function(e){if(typeof e==="undefined"){return this.Content}else{this._update(e);return this}},reposition:function(){var n=this;if(e("body").find(n.$tooltip).length!==0){n.$tooltip.css("width","");n.elProxyPosition=n._repositionInfo(n.$elProxy);var r=null,i=e(t).width(),s=n.elProxyPosition,o=n.$tooltip.outerWidth(false),u=n.$tooltip.innerWidth()+1,a=n.$tooltip.outerHeight(false);if(n.$elProxy.is("area")){var f=n.$elProxy.attr("shape"),l=n.$elProxy.parent().attr("name"),c=e('img[usemap="#'+l+'"]'),h=c.offset().left,p=c.offset().top,d=n.$elProxy.attr("coords")!==undefined?n.$elProxy.attr("coords").split(","):undefined;if(f=="circle"){var v=parseInt(d[0]),m=parseInt(d[1]),g=parseInt(d[2]);s.dimension.height=g*2;s.dimension.width=g*2;s.offset.top=p+m-g;s.offset.left=h+v-g}else if(f=="rect"){var v=parseInt(d[0]),m=parseInt(d[1]),y=parseInt(d[2]),b=parseInt(d[3]);s.dimension.height=b-m;s.dimension.width=y-v;s.offset.top=p+m;s.offset.left=h+v}else if(f=="poly"){var w=[],E=[],S=0,x=0,T=0,N=0,C="even";for(var k=0;kT){T=L;if(k===0){S=T}}if(LN){N=L;if(k==1){x=N}}if(Li){r=A-(i+n-o);A=i+n-o}}function B(n,r){if(s.offset.top-e(t).scrollTop()-a-_-12<0&&r.indexOf("top")>-1){P=n}if(s.offset.top+s.dimension.height+a+12+_>e(t).scrollTop()+e(t).height()&&r.indexOf("bottom")>-1){P=n;M=s.offset.top-a-_-12}}if(P=="top"){var j=s.offset.left+o-(s.offset.left+s.dimension.width);A=s.offset.left+D-j/2;M=s.offset.top-a-_-12;H();B("bottom","top")}if(P=="top-left"){A=s.offset.left+D;M=s.offset.top-a-_-12;H();B("bottom-left","top-left")}if(P=="top-right"){A=s.offset.left+s.dimension.width+D-o;M=s.offset.top-a-_-12;H();B("bottom-right","top-right")}if(P=="bottom"){var j=s.offset.left+o-(s.offset.left+s.dimension.width);A=s.offset.left-j/2+D;M=s.offset.top+s.dimension.height+_+12;H();B("top","bottom")}if(P=="bottom-left"){A=s.offset.left+D;M=s.offset.top+s.dimension.height+_+12;H();B("top-left","bottom-left")}if(P=="bottom-right"){A=s.offset.left+s.dimension.width+D-o;M=s.offset.top+s.dimension.height+_+12;H();B("top-right","bottom-right")}if(P=="left"){A=s.offset.left-D-o-12;O=s.offset.left+D+s.dimension.width+12;var F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_;if(A<0&&O+o>i){var I=parseFloat(n.$tooltip.css("border-width"))*2,q=o+A-I;n.$tooltip.css("width",q+"px");a=n.$tooltip.outerHeight(false);A=s.offset.left-D-q-12-I;F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_}else if(A<0){A=s.offset.left+D+s.dimension.width+12;r="left"}}if(P=="right"){A=s.offset.left+D+s.dimension.width+12;O=s.offset.left-D-o-12;var F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_;if(A+o>i&&O<0){var I=parseFloat(n.$tooltip.css("border-width"))*2,q=i-A-I;n.$tooltip.css("width",q+"px");a=n.$tooltip.outerHeight(false);F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_}else if(A+o>i){A=s.offset.left-D-o-12;r="right"}}if(n.options.arrow){var R="tooltipster-arrow-"+P;if(n.options.arrowColor.length<1){var U=n.$tooltip.css("background-color")}else{var U=n.options.arrowColor}if(!r){r=""}else if(r=="left"){R="tooltipster-arrow-right";r=""}else if(r=="right"){R="tooltipster-arrow-left";r=""}else{r="left:"+Math.round(r)+"px;"}if(P=="top"||P=="top-left"||P=="top-right"){var z=parseFloat(n.$tooltip.css("border-bottom-width")),W=n.$tooltip.css("border-bottom-color")}else if(P=="bottom"||P=="bottom-left"||P=="bottom-right"){var z=parseFloat(n.$tooltip.css("border-top-width")),W=n.$tooltip.css("border-top-color")}else if(P=="left"){var z=parseFloat(n.$tooltip.css("border-right-width")),W=n.$tooltip.css("border-right-color")}else if(P=="right"){var z=parseFloat(n.$tooltip.css("border-left-width")),W=n.$tooltip.css("border-left-color")}else{var z=parseFloat(n.$tooltip.css("border-bottom-width")),W=n.$tooltip.css("border-bottom-color")}if(z>1){z++}var X="";if(z!==0){var V="",J="border-color: "+W+";";if(R.indexOf("bottom")!==-1){V="margin-top: -"+Math.round(z)+"px;"}else if(R.indexOf("top")!==-1){V="margin-bottom: -"+Math.round(z)+"px;"}else if(R.indexOf("left")!==-1){V="margin-right: -"+Math.round(z)+"px;"}else if(R.indexOf("right")!==-1){V="margin-left: -"+Math.round(z)+"px;"}X=''}n.$tooltip.find(".tooltipster-arrow").remove();var K='
'+X+'
';n.$tooltip.append(K)}n.$tooltip.css({top:Math.round(M)+"px",left:Math.round(A)+"px"})}return n},enable:function(){this.enabled=true;return this},disable:function(){this.hide();this.enabled=false;return this},destroy:function(){var t=this;t.hide();if(t.$el[0]!==t.$elProxy[0]){t.$elProxy.remove()}t.$el.removeData(t.namespace).off("."+t.namespace);var n=t.$el.data("tooltipster-ns");if(n.length===1){var r=null;if(t.options.restoration==="previous"){r=t.$el.data("tooltipster-initialTitle")}else if(t.options.restoration==="current"){r=typeof t.Content==="string"?t.Content:e("
").append(t.Content).html()}if(r){t.$el.attr("title",r)}t.$el.removeClass("tooltipstered").removeData("tooltipster-ns").removeData("tooltipster-initialTitle")}else{n=e.grep(n,function(e,n){return e!==t.namespace});t.$el.data("tooltipster-ns",n)}return t},elementIcon:function(){return this.$el[0]!==this.$elProxy[0]?this.$elProxy[0]:undefined},elementTooltip:function(){return this.$tooltip?this.$tooltip[0]:undefined},option:function(e,t){if(typeof t=="undefined")return this.options[e];else{this.options[e]=t;return this}},status:function(){return this.Status}};e.fn[r]=function(){var t=arguments;if(this.length===0){if(typeof t[0]==="string"){var n=true;switch(t[0]){case"setDefaults":e.extend(i,t[1]);break;default:n=false;break}if(n)return true;else return this}else{return this}}else{if(typeof t[0]==="string"){var r="#*$~&";this.each(function(){var n=e(this).data("tooltipster-ns"),i=n?e(this).data(n[0]):null;if(i){if(typeof i[t[0]]==="function"){var s=i[t[0]](t[1],t[2])}else{throw new Error('Unknown method .tooltipster("'+t[0]+'")')}if(s!==i){r=s;return false}}else{throw new Error("You called Tooltipster's \""+t[0]+'" method on an uninitialized element')}});return r!=="#*$~&"?r:this}else{var o=[],u=t[0]&&typeof t[0].multiple!=="undefined",a=u&&t[0].multiple||!u&&i.multiple,f=t[0]&&typeof t[0].debug!=="undefined",l=f&&t[0].debug||!f&&i.debug;this.each(function(){var n=false,r=e(this).data("tooltipster-ns"),i=null;if(!r){n=true}else if(a){n=true}else if(l){console.log('Tooltipster: one or more tooltips are already attached to this element: ignoring. Use the "multiple" option to attach more tooltips.')}if(n){i=new s(this,t[0]);if(!r)r=[];r.push(i.namespace);e(this).data("tooltipster-ns",r);e(this).data(i.namespace,i)}o.push(i)});if(a)return o;else return this}}};var u=!!("ontouchstart"in t);var a=false;e("body").one("mousemove",function(){a=true})})(jQuery,window,document); -------------------------------------------------------------------------------- /app/lib/underscore-min.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"underscore-min.js","sources":["underscore.js"],"names":["createReduce","dir","iterator","obj","iteratee","memo","keys","index","length","currentKey","context","optimizeCb","isArrayLike","_","arguments","createIndexFinder","array","predicate","cb","collectNonEnumProps","nonEnumIdx","nonEnumerableProps","constructor","proto","isFunction","prototype","ObjProto","prop","has","contains","push","root","this","previousUnderscore","ArrayProto","Array","Object","FuncProto","Function","slice","toString","hasOwnProperty","nativeIsArray","isArray","nativeKeys","nativeBind","bind","nativeCreate","create","Ctor","_wrapped","exports","module","VERSION","func","argCount","value","call","other","collection","accumulator","apply","identity","isObject","matcher","property","Infinity","createAssigner","keysFunc","undefinedOnly","source","l","i","key","baseCreate","result","MAX_ARRAY_INDEX","Math","pow","each","forEach","map","collect","results","reduce","foldl","inject","reduceRight","foldr","find","detect","findIndex","findKey","filter","select","list","reject","negate","every","all","some","any","includes","include","target","fromIndex","values","indexOf","invoke","method","args","isFunc","pluck","where","attrs","findWhere","max","computed","lastComputed","min","shuffle","rand","set","shuffled","random","sample","n","guard","sortBy","criteria","sort","left","right","a","b","group","behavior","groupBy","indexBy","countBy","toArray","size","partition","pass","fail","first","head","take","initial","last","rest","tail","drop","compact","flatten","input","shallow","strict","startIndex","output","idx","isArguments","j","len","without","difference","uniq","unique","isSorted","isBoolean","seen","union","intersection","argsLength","item","zip","unzip","object","sortedIndex","isNaN","lastIndexOf","from","findLastIndex","low","high","mid","floor","range","start","stop","step","ceil","executeBound","sourceFunc","boundFunc","callingContext","self","TypeError","bound","concat","partial","boundArgs","position","bindAll","Error","memoize","hasher","cache","address","delay","wait","setTimeout","defer","throttle","options","timeout","previous","later","leading","now","remaining","clearTimeout","trailing","debounce","immediate","timestamp","callNow","wrap","wrapper","compose","after","times","before","once","hasEnumBug","propertyIsEnumerable","allKeys","mapObject","pairs","invert","functions","methods","names","extend","extendOwn","assign","pick","oiteratee","omit","String","defaults","clone","tap","interceptor","isMatch","eq","aStack","bStack","className","areArrays","aCtor","bCtor","pop","isEqual","isEmpty","isString","isElement","nodeType","type","name","Int8Array","isFinite","parseFloat","isNumber","isNull","isUndefined","noConflict","constant","noop","propertyOf","matches","accum","Date","getTime","escapeMap","&","<",">","\"","'","`","unescapeMap","createEscaper","escaper","match","join","testRegexp","RegExp","replaceRegexp","string","test","replace","escape","unescape","fallback","idCounter","uniqueId","prefix","id","templateSettings","evaluate","interpolate","noMatch","escapes","\\","\r","\n","
","
","escapeChar","template","text","settings","oldSettings","offset","variable","render","e","data","argument","chain","instance","_chain","mixin","valueOf","toJSON","define","amd"],"mappings":"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"} --------------------------------------------------------------------------------